Lines Matching refs:dispc

37 #include "dispc.h"
50 #define REG_GET(dispc, idx, start, end) \
51 FLD_GET(dispc_read_reg(dispc, idx), start, end)
53 #define REG_FLD_MOD(dispc, idx, val, start, end) \
54 dispc_write_reg(dispc, idx, \
55 FLD_MOD(dispc_read_reg(dispc, idx), val, start, end))
102 int (*calc_scaling)(struct dispc_device *dispc,
344 static unsigned long dispc_fclk_rate(struct dispc_device *dispc);
345 static unsigned long dispc_core_clk_rate(struct dispc_device *dispc);
346 static unsigned long dispc_mgr_lclk_rate(struct dispc_device *dispc,
348 static unsigned long dispc_mgr_pclk_rate(struct dispc_device *dispc,
351 static unsigned long dispc_plane_pclk_rate(struct dispc_device *dispc,
353 static unsigned long dispc_plane_lclk_rate(struct dispc_device *dispc,
356 static inline void dispc_write_reg(struct dispc_device *dispc, u16 idx, u32 val)
358 __raw_writel(val, dispc->base + idx);
361 static inline u32 dispc_read_reg(struct dispc_device *dispc, u16 idx)
363 return __raw_readl(dispc->base + idx);
366 static u32 mgr_fld_read(struct dispc_device *dispc, enum omap_channel channel,
371 return REG_GET(dispc, rfld->reg, rfld->high, rfld->low);
374 static void mgr_fld_write(struct dispc_device *dispc, enum omap_channel channel,
379 REG_FLD_MOD(dispc, rfld->reg, val, rfld->high, rfld->low);
382 int dispc_get_num_ovls(struct dispc_device *dispc)
384 return dispc->feat->num_ovls;
387 int dispc_get_num_mgrs(struct dispc_device *dispc)
389 return dispc->feat->num_mgrs;
392 static void dispc_get_reg_field(struct dispc_device *dispc,
396 BUG_ON(id >= dispc->feat->num_reg_fields);
398 *start = dispc->feat->reg_fields[id].start;
399 *end = dispc->feat->reg_fields[id].end;
402 static bool dispc_has_feature(struct dispc_device *dispc,
407 for (i = 0; i < dispc->feat->num_features; i++) {
408 if (dispc->feat->features[i] == id)
415 #define SR(dispc, reg) \
416 dispc->ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(dispc, DISPC_##reg)
417 #define RR(dispc, reg) \
418 dispc_write_reg(dispc, DISPC_##reg, dispc->ctx[DISPC_##reg / sizeof(u32)])
420 static void dispc_save_context(struct dispc_device *dispc)
426 SR(dispc, IRQENABLE);
427 SR(dispc, CONTROL);
428 SR(dispc, CONFIG);
429 SR(dispc, LINE_NUMBER);
430 if (dispc_has_feature(dispc, FEAT_ALPHA_FIXED_ZORDER) ||
431 dispc_has_feature(dispc, FEAT_ALPHA_FREE_ZORDER))
432 SR(dispc, GLOBAL_ALPHA);
433 if (dispc_has_feature(dispc, FEAT_MGR_LCD2)) {
434 SR(dispc, CONTROL2);
435 SR(dispc, CONFIG2);
437 if (dispc_has_feature(dispc, FEAT_MGR_LCD3)) {
438 SR(dispc, CONTROL3);
439 SR(dispc, CONFIG3);
442 for (i = 0; i < dispc_get_num_mgrs(dispc); i++) {
443 SR(dispc, DEFAULT_COLOR(i));
444 SR(dispc, TRANS_COLOR(i));
445 SR(dispc, SIZE_MGR(i));
448 SR(dispc, TIMING_H(i));
449 SR(dispc, TIMING_V(i));
450 SR(dispc, POL_FREQ(i));
451 SR(dispc, DIVISORo(i));
453 SR(dispc, DATA_CYCLE1(i));
454 SR(dispc, DATA_CYCLE2(i));
455 SR(dispc, DATA_CYCLE3(i));
457 if (dispc_has_feature(dispc, FEAT_CPR)) {
458 SR(dispc, CPR_COEF_R(i));
459 SR(dispc, CPR_COEF_G(i));
460 SR(dispc, CPR_COEF_B(i));
464 for (i = 0; i < dispc_get_num_ovls(dispc); i++) {
465 SR(dispc, OVL_BA0(i));
466 SR(dispc, OVL_BA1(i));
467 SR(dispc, OVL_POSITION(i));
468 SR(dispc, OVL_SIZE(i));
469 SR(dispc, OVL_ATTRIBUTES(i));
470 SR(dispc, OVL_FIFO_THRESHOLD(i));
471 SR(dispc, OVL_ROW_INC(i));
472 SR(dispc, OVL_PIXEL_INC(i));
473 if (dispc_has_feature(dispc, FEAT_PRELOAD))
474 SR(dispc, OVL_PRELOAD(i));
476 SR(dispc, OVL_WINDOW_SKIP(i));
477 SR(dispc, OVL_TABLE_BA(i));
480 SR(dispc, OVL_FIR(i));
481 SR(dispc, OVL_PICTURE_SIZE(i));
482 SR(dispc, OVL_ACCU0(i));
483 SR(dispc, OVL_ACCU1(i));
486 SR(dispc, OVL_FIR_COEF_H(i, j));
489 SR(dispc, OVL_FIR_COEF_HV(i, j));
492 SR(dispc, OVL_CONV_COEF(i, j));
494 if (dispc_has_feature(dispc, FEAT_FIR_COEF_V)) {
496 SR(dispc, OVL_FIR_COEF_V(i, j));
499 if (dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE)) {
500 SR(dispc, OVL_BA0_UV(i));
501 SR(dispc, OVL_BA1_UV(i));
502 SR(dispc, OVL_FIR2(i));
503 SR(dispc, OVL_ACCU2_0(i));
504 SR(dispc, OVL_ACCU2_1(i));
507 SR(dispc, OVL_FIR_COEF_H2(i, j));
510 SR(dispc, OVL_FIR_COEF_HV2(i, j));
513 SR(dispc, OVL_FIR_COEF_V2(i, j));
515 if (dispc_has_feature(dispc, FEAT_ATTR2))
516 SR(dispc, OVL_ATTRIBUTES2(i));
519 if (dispc_has_feature(dispc, FEAT_CORE_CLK_DIV))
520 SR(dispc, DIVISOR);
522 dispc->ctx_valid = true;
527 static void dispc_restore_context(struct dispc_device *dispc)
533 if (!dispc->ctx_valid)
536 /*RR(dispc, IRQENABLE);*/
537 /*RR(dispc, CONTROL);*/
538 RR(dispc, CONFIG);
539 RR(dispc, LINE_NUMBER);
540 if (dispc_has_feature(dispc, FEAT_ALPHA_FIXED_ZORDER) ||
541 dispc_has_feature(dispc, FEAT_ALPHA_FREE_ZORDER))
542 RR(dispc, GLOBAL_ALPHA);
543 if (dispc_has_feature(dispc, FEAT_MGR_LCD2))
544 RR(dispc, CONFIG2);
545 if (dispc_has_feature(dispc, FEAT_MGR_LCD3))
546 RR(dispc, CONFIG3);
548 for (i = 0; i < dispc_get_num_mgrs(dispc); i++) {
549 RR(dispc, DEFAULT_COLOR(i));
550 RR(dispc, TRANS_COLOR(i));
551 RR(dispc, SIZE_MGR(i));
554 RR(dispc, TIMING_H(i));
555 RR(dispc, TIMING_V(i));
556 RR(dispc, POL_FREQ(i));
557 RR(dispc, DIVISORo(i));
559 RR(dispc, DATA_CYCLE1(i));
560 RR(dispc, DATA_CYCLE2(i));
561 RR(dispc, DATA_CYCLE3(i));
563 if (dispc_has_feature(dispc, FEAT_CPR)) {
564 RR(dispc, CPR_COEF_R(i));
565 RR(dispc, CPR_COEF_G(i));
566 RR(dispc, CPR_COEF_B(i));
570 for (i = 0; i < dispc_get_num_ovls(dispc); i++) {
571 RR(dispc, OVL_BA0(i));
572 RR(dispc, OVL_BA1(i));
573 RR(dispc, OVL_POSITION(i));
574 RR(dispc, OVL_SIZE(i));
575 RR(dispc, OVL_ATTRIBUTES(i));
576 RR(dispc, OVL_FIFO_THRESHOLD(i));
577 RR(dispc, OVL_ROW_INC(i));
578 RR(dispc, OVL_PIXEL_INC(i));
579 if (dispc_has_feature(dispc, FEAT_PRELOAD))
580 RR(dispc, OVL_PRELOAD(i));
582 RR(dispc, OVL_WINDOW_SKIP(i));
583 RR(dispc, OVL_TABLE_BA(i));
586 RR(dispc, OVL_FIR(i));
587 RR(dispc, OVL_PICTURE_SIZE(i));
588 RR(dispc, OVL_ACCU0(i));
589 RR(dispc, OVL_ACCU1(i));
592 RR(dispc, OVL_FIR_COEF_H(i, j));
595 RR(dispc, OVL_FIR_COEF_HV(i, j));
598 RR(dispc, OVL_CONV_COEF(i, j));
600 if (dispc_has_feature(dispc, FEAT_FIR_COEF_V)) {
602 RR(dispc, OVL_FIR_COEF_V(i, j));
605 if (dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE)) {
606 RR(dispc, OVL_BA0_UV(i));
607 RR(dispc, OVL_BA1_UV(i));
608 RR(dispc, OVL_FIR2(i));
609 RR(dispc, OVL_ACCU2_0(i));
610 RR(dispc, OVL_ACCU2_1(i));
613 RR(dispc, OVL_FIR_COEF_H2(i, j));
616 RR(dispc, OVL_FIR_COEF_HV2(i, j));
619 RR(dispc, OVL_FIR_COEF_V2(i, j));
621 if (dispc_has_feature(dispc, FEAT_ATTR2))
622 RR(dispc, OVL_ATTRIBUTES2(i));
625 if (dispc_has_feature(dispc, FEAT_CORE_CLK_DIV))
626 RR(dispc, DIVISOR);
629 RR(dispc, CONTROL);
630 if (dispc_has_feature(dispc, FEAT_MGR_LCD2))
631 RR(dispc, CONTROL2);
632 if (dispc_has_feature(dispc, FEAT_MGR_LCD3))
633 RR(dispc, CONTROL3);
635 dispc_clear_irqstatus(dispc, DISPC_IRQ_SYNC_LOST_DIGIT);
641 RR(dispc, IRQENABLE);
649 int dispc_runtime_get(struct dispc_device *dispc)
655 r = pm_runtime_get_sync(&dispc->pdev->dev);
657 pm_runtime_put_noidle(&dispc->pdev->dev);
663 void dispc_runtime_put(struct dispc_device *dispc)
669 r = pm_runtime_put_sync(&dispc->pdev->dev);
673 u32 dispc_mgr_get_vsync_irq(struct dispc_device *dispc,
679 u32 dispc_mgr_get_framedone_irq(struct dispc_device *dispc,
682 if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc->feat->no_framedone_tv)
688 u32 dispc_mgr_get_sync_lost_irq(struct dispc_device *dispc,
694 u32 dispc_wb_get_framedone_irq(struct dispc_device *dispc)
699 void dispc_mgr_enable(struct dispc_device *dispc,
702 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_ENABLE, enable);
704 mgr_fld_read(dispc, channel, DISPC_MGR_FLD_ENABLE);
707 static bool dispc_mgr_is_enabled(struct dispc_device *dispc,
710 return !!mgr_fld_read(dispc, channel, DISPC_MGR_FLD_ENABLE);
713 bool dispc_mgr_go_busy(struct dispc_device *dispc,
716 return mgr_fld_read(dispc, channel, DISPC_MGR_FLD_GO) == 1;
719 void dispc_mgr_go(struct dispc_device *dispc, enum omap_channel channel)
721 WARN_ON(!dispc_mgr_is_enabled(dispc, channel));
722 WARN_ON(dispc_mgr_go_busy(dispc, channel));
726 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_GO, 1);
729 bool dispc_wb_go_busy(struct dispc_device *dispc)
731 return REG_GET(dispc, DISPC_CONTROL2, 6, 6) == 1;
734 void dispc_wb_go(struct dispc_device *dispc)
739 enable = REG_GET(dispc, DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1;
744 go = REG_GET(dispc, DISPC_CONTROL2, 6, 6) == 1;
750 REG_FLD_MOD(dispc, DISPC_CONTROL2, 1, 6, 6);
753 static void dispc_ovl_write_firh_reg(struct dispc_device *dispc,
757 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_H(plane, reg), value);
760 static void dispc_ovl_write_firhv_reg(struct dispc_device *dispc,
764 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_HV(plane, reg), value);
767 static void dispc_ovl_write_firv_reg(struct dispc_device *dispc,
771 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_V(plane, reg), value);
774 static void dispc_ovl_write_firh2_reg(struct dispc_device *dispc,
780 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_H2(plane, reg), value);
783 static void dispc_ovl_write_firhv2_reg(struct dispc_device *dispc,
789 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_HV2(plane, reg), value);
792 static void dispc_ovl_write_firv2_reg(struct dispc_device *dispc,
798 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_V2(plane, reg), value);
801 static void dispc_ovl_set_scale_coef(struct dispc_device *dispc,
813 dev_err(&dispc->pdev->dev, "%s: failed to find scale coefs\n",
831 dispc_ovl_write_firh_reg(dispc, plane, i, h);
832 dispc_ovl_write_firhv_reg(dispc, plane, i, hv);
834 dispc_ovl_write_firh2_reg(dispc, plane, i, h);
835 dispc_ovl_write_firhv2_reg(dispc, plane, i, hv);
846 dispc_ovl_write_firv_reg(dispc, plane, i, v);
848 dispc_ovl_write_firv2_reg(dispc, plane, i, v);
858 static void dispc_ovl_write_color_conv_coef(struct dispc_device *dispc,
864 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry));
865 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy, ct->rcb));
866 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr));
867 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by));
868 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb));
870 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);
907 static void dispc_ovl_set_csc(struct dispc_device *dispc,
930 dispc_ovl_write_color_conv_coef(dispc, plane, csc);
933 static void dispc_ovl_set_ba0(struct dispc_device *dispc,
936 dispc_write_reg(dispc, DISPC_OVL_BA0(plane), paddr);
939 static void dispc_ovl_set_ba1(struct dispc_device *dispc,
942 dispc_write_reg(dispc, DISPC_OVL_BA1(plane), paddr);
945 static void dispc_ovl_set_ba0_uv(struct dispc_device *dispc,
948 dispc_write_reg(dispc, DISPC_OVL_BA0_UV(plane), paddr);
951 static void dispc_ovl_set_ba1_uv(struct dispc_device *dispc,
954 dispc_write_reg(dispc, DISPC_OVL_BA1_UV(plane), paddr);
957 static void dispc_ovl_set_pos(struct dispc_device *dispc,
968 dispc_write_reg(dispc, DISPC_OVL_POSITION(plane), val);
971 static void dispc_ovl_set_input_size(struct dispc_device *dispc,
978 dispc_write_reg(dispc, DISPC_OVL_SIZE(plane), val);
980 dispc_write_reg(dispc, DISPC_OVL_PICTURE_SIZE(plane), val);
983 static void dispc_ovl_set_output_size(struct dispc_device *dispc,
994 dispc_write_reg(dispc, DISPC_OVL_PICTURE_SIZE(plane), val);
996 dispc_write_reg(dispc, DISPC_OVL_SIZE(plane), val);
999 static void dispc_ovl_set_zorder(struct dispc_device *dispc,
1006 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
1009 static void dispc_ovl_enable_zorder_planes(struct dispc_device *dispc)
1013 if (!dispc_has_feature(dispc, FEAT_ALPHA_FREE_ZORDER))
1016 for (i = 0; i < dispc_get_num_ovls(dispc); i++)
1017 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
1020 static void dispc_ovl_set_pre_mult_alpha(struct dispc_device *dispc,
1028 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
1031 static void dispc_ovl_setup_global_alpha(struct dispc_device *dispc,
1043 REG_FLD_MOD(dispc, DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift);
1046 static void dispc_ovl_set_pix_inc(struct dispc_device *dispc,
1049 dispc_write_reg(dispc, DISPC_OVL_PIXEL_INC(plane), inc);
1052 static void dispc_ovl_set_row_inc(struct dispc_device *dispc,
1055 dispc_write_reg(dispc, DISPC_OVL_ROW_INC(plane), inc);
1058 static void dispc_ovl_set_color_mode(struct dispc_device *dispc,
1128 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
1131 static void dispc_ovl_configure_burst_type(struct dispc_device *dispc,
1135 if (dispc_has_feature(dispc, FEAT_BURST_2D) == 0)
1139 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), 1, 29, 29);
1141 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), 0, 29, 29);
1144 static void dispc_ovl_set_channel_out(struct dispc_device *dispc,
1166 val = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
1167 if (dispc_has_feature(dispc, FEAT_MGR_LCD2)) {
1182 if (dispc_has_feature(dispc, FEAT_MGR_LCD3)) {
1204 dispc_write_reg(dispc, DISPC_OVL_ATTRIBUTES(plane), val);
1207 static enum omap_channel dispc_ovl_get_channel_out(struct dispc_device *dispc,
1227 val = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
1232 if (!dispc_has_feature(dispc, FEAT_MGR_LCD2))
1248 static void dispc_ovl_set_burst_size(struct dispc_device *dispc,
1256 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), burst_size,
1260 static void dispc_configure_burst_sizes(struct dispc_device *dispc)
1266 for (i = 0; i < dispc_get_num_ovls(dispc); ++i)
1267 dispc_ovl_set_burst_size(dispc, i, burst_size);
1268 if (dispc->feat->has_writeback)
1269 dispc_ovl_set_burst_size(dispc, OMAP_DSS_WB, burst_size);
1272 static u32 dispc_ovl_get_burst_size(struct dispc_device *dispc,
1276 return dispc->feat->burst_size_unit * 8;
1279 bool dispc_ovl_color_mode_supported(struct dispc_device *dispc,
1285 modes = dispc->feat->supported_color_modes[plane];
1295 const u32 *dispc_ovl_get_color_modes(struct dispc_device *dispc,
1298 return dispc->feat->supported_color_modes[plane];
1301 static void dispc_mgr_enable_cpr(struct dispc_device *dispc,
1307 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_CPR, enable);
1310 static void dispc_mgr_set_cpr_coef(struct dispc_device *dispc,
1326 dispc_write_reg(dispc, DISPC_CPR_COEF_R(channel), coef_r);
1327 dispc_write_reg(dispc, DISPC_CPR_COEF_G(channel), coef_g);
1328 dispc_write_reg(dispc, DISPC_CPR_COEF_B(channel), coef_b);
1331 static void dispc_ovl_set_vid_color_conv(struct dispc_device *dispc,
1338 val = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
1340 dispc_write_reg(dispc, DISPC_OVL_ATTRIBUTES(plane), val);
1343 static void dispc_ovl_enable_replication(struct dispc_device *dispc,
1355 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
1358 static void dispc_mgr_set_size(struct dispc_device *dispc,
1363 val = FLD_VAL(height - 1, dispc->feat->mgr_height_start, 16) |
1364 FLD_VAL(width - 1, dispc->feat->mgr_width_start, 0);
1366 dispc_write_reg(dispc, DISPC_SIZE_MGR(channel), val);
1369 static void dispc_init_fifos(struct dispc_device *dispc)
1377 unit = dispc->feat->buffer_size_unit;
1379 dispc_get_reg_field(dispc, FEAT_REG_FIFOSIZE, &start, &end);
1381 for (fifo = 0; fifo < dispc->feat->num_fifos; ++fifo) {
1382 size = REG_GET(dispc, DISPC_OVL_FIFO_SIZE_STATUS(fifo),
1385 dispc->fifo_size[fifo] = size;
1391 dispc->fifo_assignment[fifo] = fifo;
1401 if (dispc->feat->gfx_fifo_workaround) {
1404 v = dispc_read_reg(dispc, DISPC_GLOBAL_BUFFER);
1411 dispc_write_reg(dispc, DISPC_GLOBAL_BUFFER, v);
1413 dispc->fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
1414 dispc->fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
1420 for (i = 0; i < dispc_get_num_ovls(dispc); ++i) {
1425 dispc_ovl_compute_fifo_thresholds(dispc, i, &low, &high,
1428 dispc_ovl_set_fifo_threshold(dispc, i, low, high);
1431 if (dispc->feat->has_writeback) {
1436 dispc_ovl_compute_fifo_thresholds(dispc, OMAP_DSS_WB,
1440 dispc_ovl_set_fifo_threshold(dispc, OMAP_DSS_WB, low, high);
1444 static u32 dispc_ovl_get_fifo_size(struct dispc_device *dispc,
1450 for (fifo = 0; fifo < dispc->feat->num_fifos; ++fifo) {
1451 if (dispc->fifo_assignment[fifo] == plane)
1452 size += dispc->fifo_size[fifo];
1458 void dispc_ovl_set_fifo_threshold(struct dispc_device *dispc,
1465 unit = dispc->feat->buffer_size_unit;
1473 dispc_get_reg_field(dispc, FEAT_REG_FIFOHIGHTHRESHOLD,
1475 dispc_get_reg_field(dispc, FEAT_REG_FIFOLOWTHRESHOLD,
1480 REG_GET(dispc, DISPC_OVL_FIFO_THRESHOLD(plane),
1482 REG_GET(dispc, DISPC_OVL_FIFO_THRESHOLD(plane),
1486 dispc_write_reg(dispc, DISPC_OVL_FIFO_THRESHOLD(plane),
1495 if (dispc_has_feature(dispc, FEAT_PRELOAD) &&
1496 dispc->feat->set_max_preload && plane != OMAP_DSS_WB)
1497 dispc_write_reg(dispc, DISPC_OVL_PRELOAD(plane),
1501 void dispc_enable_fifomerge(struct dispc_device *dispc, bool enable)
1503 if (!dispc_has_feature(dispc, FEAT_FIFO_MERGE)) {
1509 REG_FLD_MOD(dispc, DISPC_CONFIG, enable ? 1 : 0, 14, 14);
1512 void dispc_ovl_compute_fifo_thresholds(struct dispc_device *dispc,
1521 unsigned int buf_unit = dispc->feat->buffer_size_unit;
1525 burst_size = dispc_ovl_get_burst_size(dispc, plane);
1526 ovl_fifo_size = dispc_ovl_get_fifo_size(dispc, plane);
1530 for (i = 0; i < dispc_get_num_ovls(dispc); ++i)
1531 total_fifo_size += dispc_ovl_get_fifo_size(dispc, i);
1542 if (manual_update && dispc_has_feature(dispc, FEAT_OMAP3_DSI_FIFO_BUG)) {
1559 static void dispc_ovl_set_mflag(struct dispc_device *dispc,
1569 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
1572 static void dispc_ovl_set_mflag_threshold(struct dispc_device *dispc,
1576 dispc_write_reg(dispc, DISPC_OVL_MFLAG_THRESHOLD(plane),
1580 static void dispc_init_mflag(struct dispc_device *dispc)
1594 dispc_write_reg(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE,
1598 for (i = 0; i < dispc_get_num_ovls(dispc); ++i) {
1599 u32 size = dispc_ovl_get_fifo_size(dispc, i);
1600 u32 unit = dispc->feat->buffer_size_unit;
1603 dispc_ovl_set_mflag(dispc, i, true);
1614 dispc_ovl_set_mflag_threshold(dispc, i, low, high);
1617 if (dispc->feat->has_writeback) {
1618 u32 size = dispc_ovl_get_fifo_size(dispc, OMAP_DSS_WB);
1619 u32 unit = dispc->feat->buffer_size_unit;
1622 dispc_ovl_set_mflag(dispc, OMAP_DSS_WB, true);
1633 dispc_ovl_set_mflag_threshold(dispc, OMAP_DSS_WB, low, high);
1637 static void dispc_ovl_set_fir(struct dispc_device *dispc,
1647 dispc_get_reg_field(dispc, FEAT_REG_FIRHINC,
1649 dispc_get_reg_field(dispc, FEAT_REG_FIRVINC,
1654 dispc_write_reg(dispc, DISPC_OVL_FIR(plane), val);
1657 dispc_write_reg(dispc, DISPC_OVL_FIR2(plane), val);
1661 static void dispc_ovl_set_vid_accu0(struct dispc_device *dispc,
1668 dispc_get_reg_field(dispc, FEAT_REG_HORIZONTALACCU,
1670 dispc_get_reg_field(dispc, FEAT_REG_VERTICALACCU,
1676 dispc_write_reg(dispc, DISPC_OVL_ACCU0(plane), val);
1679 static void dispc_ovl_set_vid_accu1(struct dispc_device *dispc,
1686 dispc_get_reg_field(dispc, FEAT_REG_HORIZONTALACCU,
1688 dispc_get_reg_field(dispc, FEAT_REG_VERTICALACCU,
1694 dispc_write_reg(dispc, DISPC_OVL_ACCU1(plane), val);
1697 static void dispc_ovl_set_vid_accu2_0(struct dispc_device *dispc,
1704 dispc_write_reg(dispc, DISPC_OVL_ACCU2_0(plane), val);
1707 static void dispc_ovl_set_vid_accu2_1(struct dispc_device *dispc,
1714 dispc_write_reg(dispc, DISPC_OVL_ACCU2_1(plane), val);
1717 static void dispc_ovl_set_scale_param(struct dispc_device *dispc,
1729 dispc_ovl_set_scale_coef(dispc, plane, fir_hinc, fir_vinc, five_taps,
1731 dispc_ovl_set_fir(dispc, plane, fir_hinc, fir_vinc, color_comp);
1734 static void dispc_ovl_set_accu_uv(struct dispc_device *dispc,
1819 dispc_ovl_set_vid_accu2_0(dispc, plane, h_accu2_0, v_accu2_0);
1820 dispc_ovl_set_vid_accu2_1(dispc, plane, h_accu2_1, v_accu2_1);
1823 static void dispc_ovl_set_scaling_common(struct dispc_device *dispc,
1835 dispc_ovl_set_scale_param(dispc, plane, orig_width, orig_height,
1838 l = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
1847 if (dispc_has_feature(dispc, FEAT_RESIZECONF)) {
1854 if (dispc_has_feature(dispc, FEAT_LINEBUFFERSPLIT)) {
1859 dispc_write_reg(dispc, DISPC_OVL_ATTRIBUTES(plane), l);
1874 dispc_ovl_set_vid_accu0(dispc, plane, 0, accu0);
1875 dispc_ovl_set_vid_accu1(dispc, plane, 0, accu1);
1878 static void dispc_ovl_set_scaling_uv(struct dispc_device *dispc,
1893 if (!dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE))
1899 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane),
1904 dispc_ovl_set_accu_uv(dispc, plane, orig_width, orig_height, out_width,
1947 dispc_ovl_set_scale_param(dispc, plane, orig_width, orig_height,
1952 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane),
1956 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
1958 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
1961 static void dispc_ovl_set_scaling(struct dispc_device *dispc,
1971 dispc_ovl_set_scaling_common(dispc, plane, orig_width, orig_height,
1975 dispc_ovl_set_scaling_uv(dispc, plane, orig_width, orig_height,
1980 static void dispc_ovl_set_rotation_attrs(struct dispc_device *dispc,
2037 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12);
2038 if (dispc_has_feature(dispc, FEAT_ROWREPEATENABLE))
2039 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane),
2042 if (dispc_ovl_color_mode_supported(dispc, plane, DRM_FORMAT_NV12)) {
2049 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane),
2286 static int dispc_ovl_calc_scaling_24xx(struct dispc_device *dispc,
2300 const int maxsinglelinewidth = dispc->feat->max_line_width;
2307 *core_clk = dispc->feat->calc_core_clk(pclk, in_width,
2310 *core_clk > dispc_core_clk_rate(dispc));
2335 static int dispc_ovl_calc_scaling_34xx(struct dispc_device *dispc,
2348 const int maxsinglelinewidth = dispc->feat->max_line_width;
2365 *core_clk = dispc->feat->calc_core_clk(pclk, in_width,
2379 !*core_clk || *core_clk > dispc_core_clk_rate(dispc));
2423 static int dispc_ovl_calc_scaling_44xx(struct dispc_device *dispc,
2437 const int maxsinglelinewidth = dispc->feat->max_line_width;
2438 const int maxdownscale = dispc->feat->max_downscale;
2443 in_width_max = dispc_core_clk_rate(dispc)
2482 *core_clk = dispc->feat->calc_core_clk(pclk, in_width, in_height,
2487 enum omap_overlay_caps dispc_ovl_get_caps(struct dispc_device *dispc, enum omap_plane_id plane)
2489 return dispc->feat->overlay_caps[plane];
2495 static int dispc_ovl_calc_scaling(struct dispc_device *dispc,
2507 int maxhdownscale = dispc->feat->max_downscale;
2508 int maxvdownscale = dispc->feat->max_downscale;
2516 if (dispc->feat->supported_scaler_color_modes) {
2517 const u32 *modes = dispc->feat->supported_scaler_color_modes;
2556 dispc_has_feature(dispc, FEAT_BURST_2D)) ?
2569 ret = dispc->feat->calc_scaling(dispc, pclk, lclk, vm, width, height,
2589 core_clk, dispc_core_clk_rate(dispc));
2591 if (!core_clk || core_clk > dispc_core_clk_rate(dispc)) {
2595 core_clk, dispc_core_clk_rate(dispc));
2604 void dispc_ovl_get_max_size(struct dispc_device *dispc, u16 *width, u16 *height)
2606 *width = dispc->feat->ovl_width_max;
2607 *height = dispc->feat->ovl_height_max;
2610 static int dispc_ovl_setup_common(struct dispc_device *dispc,
2637 unsigned long pclk = dispc_plane_pclk_rate(dispc, plane);
2638 unsigned long lclk = dispc_plane_lclk_rate(dispc, plane);
2673 if (!dispc_ovl_color_mode_supported(dispc, plane, fourcc))
2676 r = dispc_ovl_calc_scaling(dispc, plane, pclk, lclk, caps, vm, in_width,
2738 dispc_ovl_set_color_mode(dispc, plane, fourcc);
2740 dispc_ovl_configure_burst_type(dispc, plane, rotation_type);
2742 if (dispc->feat->reverse_ilace_field_order)
2745 dispc_ovl_set_ba0(dispc, plane, paddr + offset0);
2746 dispc_ovl_set_ba1(dispc, plane, paddr + offset1);
2749 dispc_ovl_set_ba0_uv(dispc, plane, p_uv_addr + offset0);
2750 dispc_ovl_set_ba1_uv(dispc, plane, p_uv_addr + offset1);
2753 if (dispc->feat->last_pixel_inc_missing)
2756 dispc_ovl_set_row_inc(dispc, plane, row_inc);
2757 dispc_ovl_set_pix_inc(dispc, plane, pix_inc);
2762 dispc_ovl_set_pos(dispc, plane, caps, pos_x, pos_y);
2764 dispc_ovl_set_input_size(dispc, plane, in_width, in_height);
2767 dispc_ovl_set_scaling(dispc, plane, in_width, in_height,
2770 dispc_ovl_set_output_size(dispc, plane, out_width, out_height);
2771 dispc_ovl_set_vid_color_conv(dispc, plane, cconv);
2774 dispc_ovl_set_csc(dispc, plane, color_encoding, color_range);
2777 dispc_ovl_set_rotation_attrs(dispc, plane, rotation, rotation_type,
2780 dispc_ovl_set_zorder(dispc, plane, caps, zorder);
2781 dispc_ovl_set_pre_mult_alpha(dispc, plane, caps, pre_mult_alpha);
2782 dispc_ovl_setup_global_alpha(dispc, plane, caps, global_alpha);
2784 dispc_ovl_enable_replication(dispc, plane, caps, replication);
2789 int dispc_ovl_setup(struct dispc_device *dispc,
2796 enum omap_overlay_caps caps = dispc->feat->overlay_caps[plane];
2805 dispc_ovl_set_channel_out(dispc, plane, channel);
2807 r = dispc_ovl_setup_common(dispc, plane, caps, oi->paddr, oi->p_uv_addr,
2817 int dispc_wb_setup(struct dispc_device *dispc,
2841 r = dispc_ovl_setup_common(dispc, plane, caps, wi->paddr, wi->p_uv_addr,
2867 l = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
2875 dispc_write_reg(dispc, DISPC_OVL_ATTRIBUTES(plane), l);
2879 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane), 0, 7, 0);
2895 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane), wbdelay, 7, 0);
2901 bool dispc_has_writeback(struct dispc_device *dispc)
2903 return dispc->feat->has_writeback;
2906 int dispc_ovl_enable(struct dispc_device *dispc,
2911 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
2916 static void dispc_lcd_enable_signal_polarity(struct dispc_device *dispc,
2919 if (!dispc_has_feature(dispc, FEAT_LCDENABLEPOL))
2922 REG_FLD_MOD(dispc, DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
2925 void dispc_lcd_enable_signal(struct dispc_device *dispc, bool enable)
2927 if (!dispc_has_feature(dispc, FEAT_LCDENABLESIGNAL))
2930 REG_FLD_MOD(dispc, DISPC_CONTROL, enable ? 1 : 0, 28, 28);
2933 void dispc_pck_free_enable(struct dispc_device *dispc, bool enable)
2935 if (!dispc_has_feature(dispc, FEAT_PCKFREEENABLE))
2938 REG_FLD_MOD(dispc, DISPC_CONTROL, enable ? 1 : 0, 27, 27);
2941 static void dispc_mgr_enable_fifohandcheck(struct dispc_device *dispc,
2945 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
2949 static void dispc_mgr_set_lcd_type_tft(struct dispc_device *dispc,
2952 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_STNTFT, 1);
2955 static void dispc_set_loadmode(struct dispc_device *dispc,
2958 REG_FLD_MOD(dispc, DISPC_CONFIG, mode, 2, 1);
2962 static void dispc_mgr_set_default_color(struct dispc_device *dispc,
2965 dispc_write_reg(dispc, DISPC_DEFAULT_COLOR(channel), color);
2968 static void dispc_mgr_set_trans_key(struct dispc_device *dispc,
2973 mgr_fld_write(dispc, ch, DISPC_MGR_FLD_TCKSELECTION, type);
2975 dispc_write_reg(dispc, DISPC_TRANS_COLOR(ch), trans_key);
2978 static void dispc_mgr_enable_trans_key(struct dispc_device *dispc,
2981 mgr_fld_write(dispc, ch, DISPC_MGR_FLD_TCKENABLE, enable);
2984 static void dispc_mgr_enable_alpha_fixed_zorder(struct dispc_device *dispc,
2988 if (!dispc_has_feature(dispc, FEAT_ALPHA_FIXED_ZORDER))
2992 REG_FLD_MOD(dispc, DISPC_CONFIG, enable, 18, 18);
2994 REG_FLD_MOD(dispc, DISPC_CONFIG, enable, 19, 19);
2997 void dispc_mgr_setup(struct dispc_device *dispc,
3001 dispc_mgr_set_default_color(dispc, channel, info->default_color);
3002 dispc_mgr_set_trans_key(dispc, channel, info->trans_key_type,
3004 dispc_mgr_enable_trans_key(dispc, channel, info->trans_enabled);
3005 dispc_mgr_enable_alpha_fixed_zorder(dispc, channel,
3007 if (dispc_has_feature(dispc, FEAT_CPR)) {
3008 dispc_mgr_enable_cpr(dispc, channel, info->cpr_enable);
3009 dispc_mgr_set_cpr_coef(dispc, channel, &info->cpr_coefs);
3013 static void dispc_mgr_set_tft_data_lines(struct dispc_device *dispc,
3037 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_TFTDATALINES, code);
3040 static void dispc_mgr_set_io_pad_mode(struct dispc_device *dispc,
3064 l = dispc_read_reg(dispc, DISPC_CONTROL);
3067 dispc_write_reg(dispc, DISPC_CONTROL, l);
3070 static void dispc_mgr_enable_stallmode(struct dispc_device *dispc,
3073 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_STALLMODE, enable);
3076 void dispc_mgr_set_lcd_config(struct dispc_device *dispc,
3080 dispc_mgr_set_io_pad_mode(dispc, config->io_pad_mode);
3082 dispc_mgr_enable_stallmode(dispc, channel, config->stallmode);
3083 dispc_mgr_enable_fifohandcheck(dispc, channel, config->fifohandcheck);
3085 dispc_mgr_set_clock_div(dispc, channel, &config->clock_info);
3087 dispc_mgr_set_tft_data_lines(dispc, channel, config->video_port_width);
3089 dispc_lcd_enable_signal_polarity(dispc, config->lcden_sig_polarity);
3091 dispc_mgr_set_lcd_type_tft(dispc, channel);
3094 static bool _dispc_mgr_size_ok(struct dispc_device *dispc,
3097 return width <= dispc->feat->mgr_width_max &&
3098 height <= dispc->feat->mgr_height_max;
3101 static bool _dispc_lcd_timings_ok(struct dispc_device *dispc,
3105 if (hsync_len < 1 || hsync_len > dispc->feat->sw_max ||
3106 hfp < 1 || hfp > dispc->feat->hp_max ||
3107 hbp < 1 || hbp > dispc->feat->hp_max ||
3108 vsw < 1 || vsw > dispc->feat->sw_max ||
3109 vfp < 0 || vfp > dispc->feat->vp_max ||
3110 vbp < 0 || vbp > dispc->feat->vp_max)
3115 static bool _dispc_mgr_pclk_ok(struct dispc_device *dispc,
3120 return pclk <= dispc->feat->max_lcd_pclk;
3122 return pclk <= dispc->feat->max_tv_pclk;
3125 int dispc_mgr_check_timings(struct dispc_device *dispc,
3129 if (!_dispc_mgr_size_ok(dispc, vm->hactive, vm->vactive))
3132 if (!_dispc_mgr_pclk_ok(dispc, channel, vm->pixelclock))
3140 if (!_dispc_lcd_timings_ok(dispc, vm->hsync_len,
3150 static void _dispc_mgr_set_lcd_timings(struct dispc_device *dispc,
3157 timing_h = FLD_VAL(vm->hsync_len - 1, dispc->feat->sw_start, 0) |
3158 FLD_VAL(vm->hfront_porch - 1, dispc->feat->fp_start, 8) |
3159 FLD_VAL(vm->hback_porch - 1, dispc->feat->bp_start, 20);
3160 timing_v = FLD_VAL(vm->vsync_len - 1, dispc->feat->sw_start, 0) |
3161 FLD_VAL(vm->vfront_porch, dispc->feat->fp_start, 8) |
3162 FLD_VAL(vm->vback_porch, dispc->feat->bp_start, 20);
3164 dispc_write_reg(dispc, DISPC_TIMING_H(channel), timing_h);
3165 dispc_write_reg(dispc, DISPC_TIMING_V(channel), timing_v);
3182 if (dispc->feat->supports_sync_align)
3185 dispc_write_reg(dispc, DISPC_POL_FREQ(channel), l);
3187 if (dispc->syscon_pol) {
3202 regmap_update_bits(dispc->syscon_pol, dispc->syscon_pol_offset,
3218 void dispc_mgr_set_timings(struct dispc_device *dispc,
3228 if (dispc_mgr_check_timings(dispc, channel, &t)) {
3234 _dispc_mgr_set_lcd_timings(dispc, channel, &t);
3258 if (dispc->feat->supports_double_pixel)
3259 REG_FLD_MOD(dispc, DISPC_CONTROL,
3264 dispc_mgr_set_size(dispc, channel, t.hactive, t.vactive);
3267 static void dispc_mgr_set_lcd_divisor(struct dispc_device *dispc,
3274 dispc_write_reg(dispc, DISPC_DIVISORo(channel),
3277 if (!dispc_has_feature(dispc, FEAT_CORE_CLK_DIV) &&
3279 dispc->core_clk_rate = dispc_fclk_rate(dispc) / lck_div;
3282 static void dispc_mgr_get_lcd_divisor(struct dispc_device *dispc,
3287 l = dispc_read_reg(dispc, DISPC_DIVISORo(channel));
3292 static unsigned long dispc_fclk_rate(struct dispc_device *dispc)
3297 src = dss_get_dispc_clk_source(dispc->dss);
3300 r = dss_get_dispc_clk_rate(dispc->dss);
3305 pll = dss_pll_find_by_src(dispc->dss, src);
3314 static unsigned long dispc_mgr_lclk_rate(struct dispc_device *dispc,
3323 return dispc_fclk_rate(dispc);
3325 src = dss_get_lcd_clk_source(dispc->dss, channel);
3328 r = dss_get_dispc_clk_rate(dispc->dss);
3333 pll = dss_pll_find_by_src(dispc->dss, src);
3339 lcd = REG_GET(dispc, DISPC_DIVISORo(channel), 23, 16);
3344 static unsigned long dispc_mgr_pclk_rate(struct dispc_device *dispc,
3353 l = dispc_read_reg(dispc, DISPC_DIVISORo(channel));
3357 r = dispc_mgr_lclk_rate(dispc, channel);
3361 return dispc->tv_pclk_rate;
3365 void dispc_set_tv_pclk(struct dispc_device *dispc, unsigned long pclk)
3367 dispc->tv_pclk_rate = pclk;
3370 static unsigned long dispc_core_clk_rate(struct dispc_device *dispc)
3372 return dispc->core_clk_rate;
3375 static unsigned long dispc_plane_pclk_rate(struct dispc_device *dispc,
3383 channel = dispc_ovl_get_channel_out(dispc, plane);
3385 return dispc_mgr_pclk_rate(dispc, channel);
3388 static unsigned long dispc_plane_lclk_rate(struct dispc_device *dispc,
3396 channel = dispc_ovl_get_channel_out(dispc, plane);
3398 return dispc_mgr_lclk_rate(dispc, channel);
3401 static void dispc_dump_clocks_channel(struct dispc_device *dispc,
3410 lcd_clk_src = dss_get_lcd_clk_source(dispc->dss, channel);
3415 dispc_mgr_get_lcd_divisor(dispc, channel, &lcd, &pcd);
3418 dispc_mgr_lclk_rate(dispc, channel), lcd);
3420 dispc_mgr_pclk_rate(dispc, channel), pcd);
3423 void dispc_dump_clocks(struct dispc_device *dispc, struct seq_file *s)
3429 if (dispc_runtime_get(dispc))
3434 dispc_clk_src = dss_get_dispc_clk_source(dispc->dss);
3435 seq_printf(s, "dispc fclk source = %s\n",
3438 seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate(dispc));
3440 if (dispc_has_feature(dispc, FEAT_CORE_CLK_DIV)) {
3442 l = dispc_read_reg(dispc, DISPC_DIVISOR);
3446 (dispc_fclk_rate(dispc)/lcd), lcd);
3449 dispc_dump_clocks_channel(dispc, s, OMAP_DSS_CHANNEL_LCD);
3451 if (dispc_has_feature(dispc, FEAT_MGR_LCD2))
3452 dispc_dump_clocks_channel(dispc, s, OMAP_DSS_CHANNEL_LCD2);
3453 if (dispc_has_feature(dispc, FEAT_MGR_LCD3))
3454 dispc_dump_clocks_channel(dispc, s, OMAP_DSS_CHANNEL_LCD3);
3456 dispc_runtime_put(dispc);
3461 struct dispc_device *dispc = s->private;
3478 #define DUMPREG(dispc, r) \
3479 seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(dispc, r))
3481 if (dispc_runtime_get(dispc))
3485 DUMPREG(dispc, DISPC_REVISION);
3486 DUMPREG(dispc, DISPC_SYSCONFIG);
3487 DUMPREG(dispc, DISPC_SYSSTATUS);
3488 DUMPREG(dispc, DISPC_IRQSTATUS);
3489 DUMPREG(dispc, DISPC_IRQENABLE);
3490 DUMPREG(dispc, DISPC_CONTROL);
3491 DUMPREG(dispc, DISPC_CONFIG);
3492 DUMPREG(dispc, DISPC_CAPABLE);
3493 DUMPREG(dispc, DISPC_LINE_STATUS);
3494 DUMPREG(dispc, DISPC_LINE_NUMBER);
3495 if (dispc_has_feature(dispc, FEAT_ALPHA_FIXED_ZORDER) ||
3496 dispc_has_feature(dispc, FEAT_ALPHA_FREE_ZORDER))
3497 DUMPREG(dispc, DISPC_GLOBAL_ALPHA);
3498 if (dispc_has_feature(dispc, FEAT_MGR_LCD2)) {
3499 DUMPREG(dispc, DISPC_CONTROL2);
3500 DUMPREG(dispc, DISPC_CONFIG2);
3502 if (dispc_has_feature(dispc, FEAT_MGR_LCD3)) {
3503 DUMPREG(dispc, DISPC_CONTROL3);
3504 DUMPREG(dispc, DISPC_CONFIG3);
3506 if (dispc_has_feature(dispc, FEAT_MFLAG))
3507 DUMPREG(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE);
3512 #define DUMPREG(dispc, i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
3514 dispc_read_reg(dispc, DISPC_REG(i, r)))
3519 for (i = 0; i < dispc_get_num_mgrs(dispc); i++) {
3520 DUMPREG(dispc, i, DISPC_DEFAULT_COLOR);
3521 DUMPREG(dispc, i, DISPC_TRANS_COLOR);
3522 DUMPREG(dispc, i, DISPC_SIZE_MGR);
3527 DUMPREG(dispc, i, DISPC_TIMING_H);
3528 DUMPREG(dispc, i, DISPC_TIMING_V);
3529 DUMPREG(dispc, i, DISPC_POL_FREQ);
3530 DUMPREG(dispc, i, DISPC_DIVISORo);
3532 DUMPREG(dispc, i, DISPC_DATA_CYCLE1);
3533 DUMPREG(dispc, i, DISPC_DATA_CYCLE2);
3534 DUMPREG(dispc, i, DISPC_DATA_CYCLE3);
3536 if (dispc_has_feature(dispc, FEAT_CPR)) {
3537 DUMPREG(dispc, i, DISPC_CPR_COEF_R);
3538 DUMPREG(dispc, i, DISPC_CPR_COEF_G);
3539 DUMPREG(dispc, i, DISPC_CPR_COEF_B);
3545 for (i = 0; i < dispc_get_num_ovls(dispc); i++) {
3546 DUMPREG(dispc, i, DISPC_OVL_BA0);
3547 DUMPREG(dispc, i, DISPC_OVL_BA1);
3548 DUMPREG(dispc, i, DISPC_OVL_POSITION);
3549 DUMPREG(dispc, i, DISPC_OVL_SIZE);
3550 DUMPREG(dispc, i, DISPC_OVL_ATTRIBUTES);
3551 DUMPREG(dispc, i, DISPC_OVL_FIFO_THRESHOLD);
3552 DUMPREG(dispc, i, DISPC_OVL_FIFO_SIZE_STATUS);
3553 DUMPREG(dispc, i, DISPC_OVL_ROW_INC);
3554 DUMPREG(dispc, i, DISPC_OVL_PIXEL_INC);
3556 if (dispc_has_feature(dispc, FEAT_PRELOAD))
3557 DUMPREG(dispc, i, DISPC_OVL_PRELOAD);
3558 if (dispc_has_feature(dispc, FEAT_MFLAG))
3559 DUMPREG(dispc, i, DISPC_OVL_MFLAG_THRESHOLD);
3562 DUMPREG(dispc, i, DISPC_OVL_WINDOW_SKIP);
3563 DUMPREG(dispc, i, DISPC_OVL_TABLE_BA);
3567 DUMPREG(dispc, i, DISPC_OVL_FIR);
3568 DUMPREG(dispc, i, DISPC_OVL_PICTURE_SIZE);
3569 DUMPREG(dispc, i, DISPC_OVL_ACCU0);
3570 DUMPREG(dispc, i, DISPC_OVL_ACCU1);
3571 if (dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE)) {
3572 DUMPREG(dispc, i, DISPC_OVL_BA0_UV);
3573 DUMPREG(dispc, i, DISPC_OVL_BA1_UV);
3574 DUMPREG(dispc, i, DISPC_OVL_FIR2);
3575 DUMPREG(dispc, i, DISPC_OVL_ACCU2_0);
3576 DUMPREG(dispc, i, DISPC_OVL_ACCU2_1);
3578 if (dispc_has_feature(dispc, FEAT_ATTR2))
3579 DUMPREG(dispc, i, DISPC_OVL_ATTRIBUTES2);
3582 if (dispc->feat->has_writeback) {
3584 DUMPREG(dispc, i, DISPC_OVL_BA0);
3585 DUMPREG(dispc, i, DISPC_OVL_BA1);
3586 DUMPREG(dispc, i, DISPC_OVL_SIZE);
3587 DUMPREG(dispc, i, DISPC_OVL_ATTRIBUTES);
3588 DUMPREG(dispc, i, DISPC_OVL_FIFO_THRESHOLD);
3589 DUMPREG(dispc, i, DISPC_OVL_FIFO_SIZE_STATUS);
3590 DUMPREG(dispc, i, DISPC_OVL_ROW_INC);
3591 DUMPREG(dispc, i, DISPC_OVL_PIXEL_INC);
3593 if (dispc_has_feature(dispc, FEAT_MFLAG))
3594 DUMPREG(dispc, i, DISPC_OVL_MFLAG_THRESHOLD);
3596 DUMPREG(dispc, i, DISPC_OVL_FIR);
3597 DUMPREG(dispc, i, DISPC_OVL_PICTURE_SIZE);
3598 DUMPREG(dispc, i, DISPC_OVL_ACCU0);
3599 DUMPREG(dispc, i, DISPC_OVL_ACCU1);
3600 if (dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE)) {
3601 DUMPREG(dispc, i, DISPC_OVL_BA0_UV);
3602 DUMPREG(dispc, i, DISPC_OVL_BA1_UV);
3603 DUMPREG(dispc, i, DISPC_OVL_FIR2);
3604 DUMPREG(dispc, i, DISPC_OVL_ACCU2_0);
3605 DUMPREG(dispc, i, DISPC_OVL_ACCU2_1);
3607 if (dispc_has_feature(dispc, FEAT_ATTR2))
3608 DUMPREG(dispc, i, DISPC_OVL_ATTRIBUTES2);
3615 #define DUMPREG(dispc, plane, name, i) \
3618 dispc_read_reg(dispc, DISPC_REG(plane, name, i)))
3623 for (i = 1; i < dispc_get_num_ovls(dispc); i++) {
3625 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_H, j);
3628 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_HV, j);
3631 DUMPREG(dispc, i, DISPC_OVL_CONV_COEF, j);
3633 if (dispc_has_feature(dispc, FEAT_FIR_COEF_V)) {
3635 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_V, j);
3638 if (dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE)) {
3640 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_H2, j);
3643 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_HV2, j);
3646 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_V2, j);
3650 dispc_runtime_put(dispc);
3659 int dispc_calc_clock_rates(struct dispc_device *dispc,
3674 bool dispc_div_calc(struct dispc_device *dispc, unsigned long dispc_freq,
3692 pckd_hw_min = dispc->feat->min_pcd;
3695 lck_max = dss_get_max_fck_rate(dispc->dss);
3718 if (dispc_has_feature(dispc, FEAT_CORE_CLK_DIV))
3719 fck = dispc_core_clk_rate(dispc);
3734 void dispc_mgr_set_clock_div(struct dispc_device *dispc,
3741 dispc_mgr_set_lcd_divisor(dispc, channel, cinfo->lck_div,
3745 int dispc_mgr_get_clock_div(struct dispc_device *dispc,
3751 fck = dispc_fclk_rate(dispc);
3753 cinfo->lck_div = REG_GET(dispc, DISPC_DIVISORo(channel), 23, 16);
3754 cinfo->pck_div = REG_GET(dispc, DISPC_DIVISORo(channel), 7, 0);
3762 u32 dispc_read_irqstatus(struct dispc_device *dispc)
3764 return dispc_read_reg(dispc, DISPC_IRQSTATUS);
3767 void dispc_clear_irqstatus(struct dispc_device *dispc, u32 mask)
3769 dispc_write_reg(dispc, DISPC_IRQSTATUS, mask);
3772 void dispc_write_irqenable(struct dispc_device *dispc, u32 mask)
3774 u32 old_mask = dispc_read_reg(dispc, DISPC_IRQENABLE);
3777 dispc_clear_irqstatus(dispc, (mask ^ old_mask) & mask);
3779 dispc_write_reg(dispc, DISPC_IRQENABLE, mask);
3782 dispc_read_reg(dispc, DISPC_IRQENABLE);
3785 void dispc_enable_sidle(struct dispc_device *dispc)
3788 REG_FLD_MOD(dispc, DISPC_SYSCONFIG, 2, 4, 3);
3791 void dispc_disable_sidle(struct dispc_device *dispc)
3793 REG_FLD_MOD(dispc, DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
3796 u32 dispc_mgr_gamma_size(struct dispc_device *dispc,
3801 if (!dispc->feat->has_gamma_table)
3807 static void dispc_mgr_write_gamma_table(struct dispc_device *dispc,
3811 u32 *table = dispc->gamma_table[channel];
3824 dispc_write_reg(dispc, gdesc->reg, v);
3828 static void dispc_restore_gamma_tables(struct dispc_device *dispc)
3832 if (!dispc->feat->has_gamma_table)
3835 dispc_mgr_write_gamma_table(dispc, OMAP_DSS_CHANNEL_LCD);
3837 dispc_mgr_write_gamma_table(dispc, OMAP_DSS_CHANNEL_DIGIT);
3839 if (dispc_has_feature(dispc, FEAT_MGR_LCD2))
3840 dispc_mgr_write_gamma_table(dispc, OMAP_DSS_CHANNEL_LCD2);
3842 if (dispc_has_feature(dispc, FEAT_MGR_LCD3))
3843 dispc_mgr_write_gamma_table(dispc, OMAP_DSS_CHANNEL_LCD3);
3851 void dispc_mgr_set_gamma(struct dispc_device *dispc,
3857 u32 *table = dispc->gamma_table[channel];
3863 if (!dispc->feat->has_gamma_table)
3895 if (dispc->is_enabled)
3896 dispc_mgr_write_gamma_table(dispc, channel);
3899 static int dispc_init_gamma_tables(struct dispc_device *dispc)
3903 if (!dispc->feat->has_gamma_table)
3906 for (channel = 0; channel < ARRAY_SIZE(dispc->gamma_table); channel++) {
3911 !dispc_has_feature(dispc, FEAT_MGR_LCD2))
3915 !dispc_has_feature(dispc, FEAT_MGR_LCD3))
3918 gt = devm_kmalloc_array(&dispc->pdev->dev, gdesc->len,
3923 dispc->gamma_table[channel] = gt;
3925 dispc_mgr_set_gamma(dispc, channel, NULL, 0);
3930 static void _omap_dispc_initial_config(struct dispc_device *dispc)
3935 if (dispc_has_feature(dispc, FEAT_CORE_CLK_DIV)) {
3936 l = dispc_read_reg(dispc, DISPC_DIVISOR);
3940 dispc_write_reg(dispc, DISPC_DIVISOR, l);
3942 dispc->core_clk_rate = dispc_fclk_rate(dispc);
3946 if (dispc->feat->has_gamma_table)
3947 REG_FLD_MOD(dispc, DISPC_CONFIG, 1, 3, 3);
3951 * (dispc->feat->has_gamma_table) this enables tv-out gamma tables.
3953 if (dispc_has_feature(dispc, FEAT_FUNCGATED) ||
3954 dispc->feat->has_gamma_table)
3955 REG_FLD_MOD(dispc, DISPC_CONFIG, 1, 9, 9);
3957 dispc_set_loadmode(dispc, OMAP_DSS_LOAD_FRAME_ONLY);
3959 dispc_init_fifos(dispc);
3961 dispc_configure_burst_sizes(dispc);
3963 dispc_ovl_enable_zorder_planes(dispc);
3965 if (dispc->feat->mstandby_workaround)
3966 REG_FLD_MOD(dispc, DISPC_MSTANDBY_CTRL, 1, 0, 0);
3968 if (dispc_has_feature(dispc, FEAT_MFLAG))
3969 dispc_init_mflag(dispc);
4513 struct dispc_device *dispc = arg;
4515 if (!dispc->is_enabled)
4518 return dispc->user_handler(irq, dispc->user_data);
4521 int dispc_request_irq(struct dispc_device *dispc, irq_handler_t handler,
4526 if (dispc->user_handler != NULL)
4529 dispc->user_handler = handler;
4530 dispc->user_data = dev_id;
4535 r = devm_request_irq(&dispc->pdev->dev, dispc->irq, dispc_irq_handler,
4536 IRQF_SHARED, "OMAP DISPC", dispc);
4538 dispc->user_handler = NULL;
4539 dispc->user_data = NULL;
4545 void dispc_free_irq(struct dispc_device *dispc, void *dev_id)
4547 devm_free_irq(&dispc->pdev->dev, dispc->irq, dispc);
4549 dispc->user_handler = NULL;
4550 dispc->user_data = NULL;
4553 u32 dispc_get_memory_bandwidth_limit(struct dispc_device *dispc)
4558 of_property_read_u32(dispc->pdev->dev.of_node, "max-memory-bandwidth",
4565 * Workaround for errata i734 in DSS dispc
4635 static int dispc_errata_i734_wa_init(struct dispc_device *dispc)
4637 if (!dispc->feat->has_gamma_i734_bug)
4643 i734_buf.vaddr = dma_alloc_wc(&dispc->pdev->dev, i734_buf.size,
4646 dev_err(&dispc->pdev->dev, "%s: dma_alloc_wc failed\n",
4654 static void dispc_errata_i734_wa_fini(struct dispc_device *dispc)
4656 if (!dispc->feat->has_gamma_i734_bug)
4659 dma_free_wc(&dispc->pdev->dev, i734_buf.size, i734_buf.vaddr,
4663 static void dispc_errata_i734_wa(struct dispc_device *dispc)
4665 u32 framedone_irq = dispc_mgr_get_framedone_irq(dispc,
4672 if (!dispc->feat->has_gamma_i734_bug)
4675 gatestate = REG_GET(dispc, DISPC_CONFIG, 8, 4);
4682 REG_FLD_MOD(dispc, DISPC_CONFIG, 0x1f, 8, 4);
4685 dispc_ovl_setup(dispc, OMAP_DSS_GFX, &ovli, &i734.vm, false,
4687 dispc_ovl_enable(dispc, OMAP_DSS_GFX, true);
4690 dispc_mgr_setup(dispc, OMAP_DSS_CHANNEL_LCD, &i734.mgri);
4691 dispc_calc_clock_rates(dispc, dss_get_dispc_clk_rate(dispc->dss),
4693 dispc_mgr_set_lcd_config(dispc, OMAP_DSS_CHANNEL_LCD, &lcd_conf);
4694 dispc_mgr_set_timings(dispc, OMAP_DSS_CHANNEL_LCD, &i734.vm);
4696 dispc_clear_irqstatus(dispc, framedone_irq);
4699 dispc_mgr_enable(dispc, OMAP_DSS_CHANNEL_LCD, true);
4700 dispc_mgr_enable(dispc, OMAP_DSS_CHANNEL_LCD, false);
4707 while (!(dispc_read_irqstatus(dispc) & framedone_irq)) {
4709 dev_err(&dispc->pdev->dev, "%s: framedone timeout\n",
4714 dispc_ovl_enable(dispc, OMAP_DSS_GFX, false);
4717 dispc_clear_irqstatus(dispc, 0xffffffff);
4720 REG_FLD_MOD(dispc, DISPC_CONFIG, gatestate, 8, 4);
4725 { .compatible = "ti,omap2-dispc", .data = &omap24xx_dispc_feats },
4726 { .compatible = "ti,omap3-dispc", .data = &omap36xx_dispc_feats },
4727 { .compatible = "ti,omap4-dispc", .data = &omap44xx_dispc_feats },
4728 { .compatible = "ti,omap5-dispc", .data = &omap54xx_dispc_feats },
4729 { .compatible = "ti,dra7-dispc", .data = &omap54xx_dispc_feats },
4747 struct dispc_device *dispc;
4752 dispc = kzalloc(sizeof(*dispc), GFP_KERNEL);
4753 if (!dispc)
4756 dispc->pdev = pdev;
4757 platform_set_drvdata(pdev, dispc);
4758 dispc->dss = dss;
4766 dispc->feat = soc->data;
4768 dispc->feat = of_match_device(dispc_of_match, &pdev->dev)->data;
4770 r = dispc_errata_i734_wa_init(dispc);
4774 dispc->base = devm_platform_ioremap_resource(pdev, 0);
4775 if (IS_ERR(dispc->base)) {
4776 r = PTR_ERR(dispc->base);
4780 dispc->irq = platform_get_irq(dispc->pdev, 0);
4781 if (dispc->irq < 0) {
4788 dispc->syscon_pol = syscon_regmap_lookup_by_phandle(np, "syscon-pol");
4789 if (IS_ERR(dispc->syscon_pol)) {
4791 r = PTR_ERR(dispc->syscon_pol);
4796 &dispc->syscon_pol_offset)) {
4803 r = dispc_init_gamma_tables(dispc);
4809 r = dispc_runtime_get(dispc);
4813 _omap_dispc_initial_config(dispc);
4815 rev = dispc_read_reg(dispc, DISPC_REVISION);
4819 dispc_runtime_put(dispc);
4821 dss->dispc = dispc;
4823 dispc->debugfs = dss_debugfs_create_file(dss, "dispc", dispc_dump_regs,
4824 dispc);
4831 kfree(dispc);
4837 struct dispc_device *dispc = dev_get_drvdata(dev);
4838 struct dss_device *dss = dispc->dss;
4840 dss_debugfs_remove_file(dispc->debugfs);
4842 dss->dispc = NULL;
4846 dispc_errata_i734_wa_fini(dispc);
4848 kfree(dispc);
4868 struct dispc_device *dispc = dev_get_drvdata(dev);
4870 dispc->is_enabled = false;
4874 synchronize_irq(dispc->irq);
4876 dispc_save_context(dispc);
4883 struct dispc_device *dispc = dev_get_drvdata(dev);
4891 if (REG_GET(dispc, DISPC_CONFIG, 2, 1) != OMAP_DSS_LOAD_FRAME_ONLY) {
4892 _omap_dispc_initial_config(dispc);
4894 dispc_errata_i734_wa(dispc);
4896 dispc_restore_context(dispc);
4898 dispc_restore_gamma_tables(dispc);
4901 dispc->is_enabled = true;