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))
100 int (*calc_scaling)(struct dispc_device *dispc,
342 static unsigned long dispc_fclk_rate(struct dispc_device *dispc);
343 static unsigned long dispc_core_clk_rate(struct dispc_device *dispc);
344 static unsigned long dispc_mgr_lclk_rate(struct dispc_device *dispc,
346 static unsigned long dispc_mgr_pclk_rate(struct dispc_device *dispc,
349 static unsigned long dispc_plane_pclk_rate(struct dispc_device *dispc,
351 static unsigned long dispc_plane_lclk_rate(struct dispc_device *dispc,
354 static void dispc_clear_irqstatus(struct dispc_device *dispc, u32 mask);
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 static int dispc_get_num_ovls(struct dispc_device *dispc)
384 return dispc->feat->num_ovls;
387 static 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);
660 void dispc_runtime_put(struct dispc_device *dispc)
666 r = pm_runtime_put_sync(&dispc->pdev->dev);
670 static u32 dispc_mgr_get_vsync_irq(struct dispc_device *dispc,
676 static u32 dispc_mgr_get_framedone_irq(struct dispc_device *dispc,
679 if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc->feat->no_framedone_tv)
685 static u32 dispc_mgr_get_sync_lost_irq(struct dispc_device *dispc,
691 static u32 dispc_wb_get_framedone_irq(struct dispc_device *dispc)
696 static void dispc_mgr_enable(struct dispc_device *dispc,
699 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_ENABLE, enable);
701 mgr_fld_read(dispc, channel, DISPC_MGR_FLD_ENABLE);
704 static bool dispc_mgr_is_enabled(struct dispc_device *dispc,
707 return !!mgr_fld_read(dispc, channel, DISPC_MGR_FLD_ENABLE);
710 static bool dispc_mgr_go_busy(struct dispc_device *dispc,
713 return mgr_fld_read(dispc, channel, DISPC_MGR_FLD_GO) == 1;
716 static void dispc_mgr_go(struct dispc_device *dispc, enum omap_channel channel)
718 WARN_ON(!dispc_mgr_is_enabled(dispc, channel));
719 WARN_ON(dispc_mgr_go_busy(dispc, channel));
723 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_GO, 1);
726 static bool dispc_wb_go_busy(struct dispc_device *dispc)
728 return REG_GET(dispc, DISPC_CONTROL2, 6, 6) == 1;
731 static void dispc_wb_go(struct dispc_device *dispc)
736 enable = REG_GET(dispc, DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1;
741 go = REG_GET(dispc, DISPC_CONTROL2, 6, 6) == 1;
747 REG_FLD_MOD(dispc, DISPC_CONTROL2, 1, 6, 6);
750 static void dispc_ovl_write_firh_reg(struct dispc_device *dispc,
754 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_H(plane, reg), value);
757 static void dispc_ovl_write_firhv_reg(struct dispc_device *dispc,
761 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_HV(plane, reg), value);
764 static void dispc_ovl_write_firv_reg(struct dispc_device *dispc,
768 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_V(plane, reg), value);
771 static void dispc_ovl_write_firh2_reg(struct dispc_device *dispc,
777 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_H2(plane, reg), value);
780 static void dispc_ovl_write_firhv2_reg(struct dispc_device *dispc,
786 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_HV2(plane, reg), value);
789 static void dispc_ovl_write_firv2_reg(struct dispc_device *dispc,
795 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_V2(plane, reg), value);
798 static void dispc_ovl_set_scale_coef(struct dispc_device *dispc,
810 dev_err(&dispc->pdev->dev, "%s: failed to find scale coefs\n",
828 dispc_ovl_write_firh_reg(dispc, plane, i, h);
829 dispc_ovl_write_firhv_reg(dispc, plane, i, hv);
831 dispc_ovl_write_firh2_reg(dispc, plane, i, h);
832 dispc_ovl_write_firhv2_reg(dispc, plane, i, hv);
843 dispc_ovl_write_firv_reg(dispc, plane, i, v);
845 dispc_ovl_write_firv2_reg(dispc, plane, i, v);
860 static void dispc_ovl_write_color_conv_coef(struct dispc_device *dispc,
866 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry));
867 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy, ct->rcb));
868 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr));
869 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by));
870 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb));
872 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);
877 static void dispc_wb_write_color_conv_coef(struct dispc_device *dispc,
884 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->yg, ct->yr));
885 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->crr, ct->yb));
886 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->crb, ct->crg));
887 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->cbg, ct->cbr));
888 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->cbb));
890 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);
895 static void dispc_setup_color_conv_coef(struct dispc_device *dispc)
898 int num_ovl = dispc_get_num_ovls(dispc);
917 dispc_ovl_write_color_conv_coef(dispc, i, &coefs_yuv2rgb_bt601_lim);
919 if (dispc->feat->has_writeback)
920 dispc_wb_write_color_conv_coef(dispc, &coefs_rgb2yuv_bt601_lim);
923 static void dispc_ovl_set_ba0(struct dispc_device *dispc,
926 dispc_write_reg(dispc, DISPC_OVL_BA0(plane), paddr);
929 static void dispc_ovl_set_ba1(struct dispc_device *dispc,
932 dispc_write_reg(dispc, DISPC_OVL_BA1(plane), paddr);
935 static void dispc_ovl_set_ba0_uv(struct dispc_device *dispc,
938 dispc_write_reg(dispc, DISPC_OVL_BA0_UV(plane), paddr);
941 static void dispc_ovl_set_ba1_uv(struct dispc_device *dispc,
944 dispc_write_reg(dispc, DISPC_OVL_BA1_UV(plane), paddr);
947 static void dispc_ovl_set_pos(struct dispc_device *dispc,
958 dispc_write_reg(dispc, DISPC_OVL_POSITION(plane), val);
961 static void dispc_ovl_set_input_size(struct dispc_device *dispc,
968 dispc_write_reg(dispc, DISPC_OVL_SIZE(plane), val);
970 dispc_write_reg(dispc, DISPC_OVL_PICTURE_SIZE(plane), val);
973 static void dispc_ovl_set_output_size(struct dispc_device *dispc,
984 dispc_write_reg(dispc, DISPC_OVL_PICTURE_SIZE(plane), val);
986 dispc_write_reg(dispc, DISPC_OVL_SIZE(plane), val);
989 static void dispc_ovl_set_zorder(struct dispc_device *dispc,
996 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
999 static void dispc_ovl_enable_zorder_planes(struct dispc_device *dispc)
1003 if (!dispc_has_feature(dispc, FEAT_ALPHA_FREE_ZORDER))
1006 for (i = 0; i < dispc_get_num_ovls(dispc); i++)
1007 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
1010 static void dispc_ovl_set_pre_mult_alpha(struct dispc_device *dispc,
1018 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
1021 static void dispc_ovl_setup_global_alpha(struct dispc_device *dispc,
1033 REG_FLD_MOD(dispc, DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift);
1036 static void dispc_ovl_set_pix_inc(struct dispc_device *dispc,
1039 dispc_write_reg(dispc, DISPC_OVL_PIXEL_INC(plane), inc);
1042 static void dispc_ovl_set_row_inc(struct dispc_device *dispc,
1045 dispc_write_reg(dispc, DISPC_OVL_ROW_INC(plane), inc);
1048 static void dispc_ovl_set_color_mode(struct dispc_device *dispc,
1118 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
1121 static void dispc_ovl_configure_burst_type(struct dispc_device *dispc,
1125 if (dispc_has_feature(dispc, FEAT_BURST_2D) == 0)
1129 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), 1, 29, 29);
1131 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), 0, 29, 29);
1134 static void dispc_ovl_set_channel_out(struct dispc_device *dispc,
1156 val = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
1157 if (dispc_has_feature(dispc, FEAT_MGR_LCD2)) {
1172 if (dispc_has_feature(dispc, FEAT_MGR_LCD3)) {
1194 dispc_write_reg(dispc, DISPC_OVL_ATTRIBUTES(plane), val);
1197 static enum omap_channel dispc_ovl_get_channel_out(struct dispc_device *dispc,
1217 val = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
1222 if (!dispc_has_feature(dispc, FEAT_MGR_LCD2))
1238 static void dispc_ovl_set_burst_size(struct dispc_device *dispc,
1246 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), burst_size,
1250 static void dispc_configure_burst_sizes(struct dispc_device *dispc)
1256 for (i = 0; i < dispc_get_num_ovls(dispc); ++i)
1257 dispc_ovl_set_burst_size(dispc, i, burst_size);
1258 if (dispc->feat->has_writeback)
1259 dispc_ovl_set_burst_size(dispc, OMAP_DSS_WB, burst_size);
1262 static u32 dispc_ovl_get_burst_size(struct dispc_device *dispc,
1266 return dispc->feat->burst_size_unit * 8;
1269 static bool dispc_ovl_color_mode_supported(struct dispc_device *dispc,
1275 modes = dispc->feat->supported_color_modes[plane];
1285 static const u32 *dispc_ovl_get_color_modes(struct dispc_device *dispc,
1288 return dispc->feat->supported_color_modes[plane];
1291 static void dispc_mgr_enable_cpr(struct dispc_device *dispc,
1297 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_CPR, enable);
1300 static void dispc_mgr_set_cpr_coef(struct dispc_device *dispc,
1316 dispc_write_reg(dispc, DISPC_CPR_COEF_R(channel), coef_r);
1317 dispc_write_reg(dispc, DISPC_CPR_COEF_G(channel), coef_g);
1318 dispc_write_reg(dispc, DISPC_CPR_COEF_B(channel), coef_b);
1321 static void dispc_ovl_set_vid_color_conv(struct dispc_device *dispc,
1328 val = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
1330 dispc_write_reg(dispc, DISPC_OVL_ATTRIBUTES(plane), val);
1333 static void dispc_ovl_enable_replication(struct dispc_device *dispc,
1345 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
1348 static void dispc_mgr_set_size(struct dispc_device *dispc,
1353 val = FLD_VAL(height - 1, dispc->feat->mgr_height_start, 16) |
1354 FLD_VAL(width - 1, dispc->feat->mgr_width_start, 0);
1356 dispc_write_reg(dispc, DISPC_SIZE_MGR(channel), val);
1359 static void dispc_init_fifos(struct dispc_device *dispc)
1367 unit = dispc->feat->buffer_size_unit;
1369 dispc_get_reg_field(dispc, FEAT_REG_FIFOSIZE, &start, &end);
1371 for (fifo = 0; fifo < dispc->feat->num_fifos; ++fifo) {
1372 size = REG_GET(dispc, DISPC_OVL_FIFO_SIZE_STATUS(fifo),
1375 dispc->fifo_size[fifo] = size;
1381 dispc->fifo_assignment[fifo] = fifo;
1391 if (dispc->feat->gfx_fifo_workaround) {
1394 v = dispc_read_reg(dispc, DISPC_GLOBAL_BUFFER);
1401 dispc_write_reg(dispc, DISPC_GLOBAL_BUFFER, v);
1403 dispc->fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
1404 dispc->fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
1410 for (i = 0; i < dispc_get_num_ovls(dispc); ++i) {
1415 dispc_ovl_compute_fifo_thresholds(dispc, i, &low, &high,
1418 dispc_ovl_set_fifo_threshold(dispc, i, low, high);
1421 if (dispc->feat->has_writeback) {
1426 dispc_ovl_compute_fifo_thresholds(dispc, OMAP_DSS_WB,
1430 dispc_ovl_set_fifo_threshold(dispc, OMAP_DSS_WB, low, high);
1434 static u32 dispc_ovl_get_fifo_size(struct dispc_device *dispc,
1440 for (fifo = 0; fifo < dispc->feat->num_fifos; ++fifo) {
1441 if (dispc->fifo_assignment[fifo] == plane)
1442 size += dispc->fifo_size[fifo];
1448 void dispc_ovl_set_fifo_threshold(struct dispc_device *dispc,
1455 unit = dispc->feat->buffer_size_unit;
1463 dispc_get_reg_field(dispc, FEAT_REG_FIFOHIGHTHRESHOLD,
1465 dispc_get_reg_field(dispc, FEAT_REG_FIFOLOWTHRESHOLD,
1470 REG_GET(dispc, DISPC_OVL_FIFO_THRESHOLD(plane),
1472 REG_GET(dispc, DISPC_OVL_FIFO_THRESHOLD(plane),
1476 dispc_write_reg(dispc, DISPC_OVL_FIFO_THRESHOLD(plane),
1485 if (dispc_has_feature(dispc, FEAT_PRELOAD) &&
1486 dispc->feat->set_max_preload && plane != OMAP_DSS_WB)
1487 dispc_write_reg(dispc, DISPC_OVL_PRELOAD(plane),
1491 void dispc_enable_fifomerge(struct dispc_device *dispc, bool enable)
1493 if (!dispc_has_feature(dispc, FEAT_FIFO_MERGE)) {
1499 REG_FLD_MOD(dispc, DISPC_CONFIG, enable ? 1 : 0, 14, 14);
1502 void dispc_ovl_compute_fifo_thresholds(struct dispc_device *dispc,
1511 unsigned int buf_unit = dispc->feat->buffer_size_unit;
1515 burst_size = dispc_ovl_get_burst_size(dispc, plane);
1516 ovl_fifo_size = dispc_ovl_get_fifo_size(dispc, plane);
1520 for (i = 0; i < dispc_get_num_ovls(dispc); ++i)
1521 total_fifo_size += dispc_ovl_get_fifo_size(dispc, i);
1532 if (manual_update && dispc_has_feature(dispc, FEAT_OMAP3_DSI_FIFO_BUG)) {
1549 static void dispc_ovl_set_mflag(struct dispc_device *dispc,
1559 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
1562 static void dispc_ovl_set_mflag_threshold(struct dispc_device *dispc,
1566 dispc_write_reg(dispc, DISPC_OVL_MFLAG_THRESHOLD(plane),
1570 static void dispc_init_mflag(struct dispc_device *dispc)
1584 dispc_write_reg(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE,
1588 for (i = 0; i < dispc_get_num_ovls(dispc); ++i) {
1589 u32 size = dispc_ovl_get_fifo_size(dispc, i);
1590 u32 unit = dispc->feat->buffer_size_unit;
1593 dispc_ovl_set_mflag(dispc, i, true);
1604 dispc_ovl_set_mflag_threshold(dispc, i, low, high);
1607 if (dispc->feat->has_writeback) {
1608 u32 size = dispc_ovl_get_fifo_size(dispc, OMAP_DSS_WB);
1609 u32 unit = dispc->feat->buffer_size_unit;
1612 dispc_ovl_set_mflag(dispc, OMAP_DSS_WB, true);
1623 dispc_ovl_set_mflag_threshold(dispc, OMAP_DSS_WB, low, high);
1627 static void dispc_ovl_set_fir(struct dispc_device *dispc,
1637 dispc_get_reg_field(dispc, FEAT_REG_FIRHINC,
1639 dispc_get_reg_field(dispc, FEAT_REG_FIRVINC,
1644 dispc_write_reg(dispc, DISPC_OVL_FIR(plane), val);
1647 dispc_write_reg(dispc, DISPC_OVL_FIR2(plane), val);
1651 static void dispc_ovl_set_vid_accu0(struct dispc_device *dispc,
1658 dispc_get_reg_field(dispc, FEAT_REG_HORIZONTALACCU,
1660 dispc_get_reg_field(dispc, FEAT_REG_VERTICALACCU,
1666 dispc_write_reg(dispc, DISPC_OVL_ACCU0(plane), val);
1669 static void dispc_ovl_set_vid_accu1(struct dispc_device *dispc,
1676 dispc_get_reg_field(dispc, FEAT_REG_HORIZONTALACCU,
1678 dispc_get_reg_field(dispc, FEAT_REG_VERTICALACCU,
1684 dispc_write_reg(dispc, DISPC_OVL_ACCU1(plane), val);
1687 static void dispc_ovl_set_vid_accu2_0(struct dispc_device *dispc,
1694 dispc_write_reg(dispc, DISPC_OVL_ACCU2_0(plane), val);
1697 static void dispc_ovl_set_vid_accu2_1(struct dispc_device *dispc,
1704 dispc_write_reg(dispc, DISPC_OVL_ACCU2_1(plane), val);
1707 static void dispc_ovl_set_scale_param(struct dispc_device *dispc,
1719 dispc_ovl_set_scale_coef(dispc, plane, fir_hinc, fir_vinc, five_taps,
1721 dispc_ovl_set_fir(dispc, plane, fir_hinc, fir_vinc, color_comp);
1724 static void dispc_ovl_set_accu_uv(struct dispc_device *dispc,
1809 dispc_ovl_set_vid_accu2_0(dispc, plane, h_accu2_0, v_accu2_0);
1810 dispc_ovl_set_vid_accu2_1(dispc, plane, h_accu2_1, v_accu2_1);
1813 static void dispc_ovl_set_scaling_common(struct dispc_device *dispc,
1825 dispc_ovl_set_scale_param(dispc, plane, orig_width, orig_height,
1828 l = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
1837 if (dispc_has_feature(dispc, FEAT_RESIZECONF)) {
1844 if (dispc_has_feature(dispc, FEAT_LINEBUFFERSPLIT)) {
1849 dispc_write_reg(dispc, DISPC_OVL_ATTRIBUTES(plane), l);
1864 dispc_ovl_set_vid_accu0(dispc, plane, 0, accu0);
1865 dispc_ovl_set_vid_accu1(dispc, plane, 0, accu1);
1868 static void dispc_ovl_set_scaling_uv(struct dispc_device *dispc,
1883 if (!dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE))
1889 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane),
1894 dispc_ovl_set_accu_uv(dispc, plane, orig_width, orig_height, out_width,
1937 dispc_ovl_set_scale_param(dispc, plane, orig_width, orig_height,
1942 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane),
1946 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
1948 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
1951 static void dispc_ovl_set_scaling(struct dispc_device *dispc,
1961 dispc_ovl_set_scaling_common(dispc, plane, orig_width, orig_height,
1965 dispc_ovl_set_scaling_uv(dispc, plane, orig_width, orig_height,
1970 static void dispc_ovl_set_rotation_attrs(struct dispc_device *dispc,
2027 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12);
2028 if (dispc_has_feature(dispc, FEAT_ROWREPEATENABLE))
2029 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane),
2032 if (dispc_ovl_color_mode_supported(dispc, plane, DRM_FORMAT_NV12)) {
2039 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane),
2277 static int dispc_ovl_calc_scaling_24xx(struct dispc_device *dispc,
2291 const int maxsinglelinewidth = dispc->feat->max_line_width;
2298 *core_clk = dispc->feat->calc_core_clk(pclk, in_width,
2301 *core_clk > dispc_core_clk_rate(dispc));
2326 static int dispc_ovl_calc_scaling_34xx(struct dispc_device *dispc,
2339 const int maxsinglelinewidth = dispc->feat->max_line_width;
2356 *core_clk = dispc->feat->calc_core_clk(pclk, in_width,
2370 !*core_clk || *core_clk > dispc_core_clk_rate(dispc));
2414 static int dispc_ovl_calc_scaling_44xx(struct dispc_device *dispc,
2428 const int maxsinglelinewidth = dispc->feat->max_line_width;
2429 const int maxdownscale = dispc->feat->max_downscale;
2434 in_width_max = dispc_core_clk_rate(dispc)
2473 *core_clk = dispc->feat->calc_core_clk(pclk, in_width, in_height,
2481 static int dispc_ovl_calc_scaling(struct dispc_device *dispc,
2493 int maxhdownscale = dispc->feat->max_downscale;
2494 int maxvdownscale = dispc->feat->max_downscale;
2502 if (dispc->feat->supported_scaler_color_modes) {
2503 const u32 *modes = dispc->feat->supported_scaler_color_modes;
2542 dispc_has_feature(dispc, FEAT_BURST_2D)) ?
2555 ret = dispc->feat->calc_scaling(dispc, pclk, lclk, vm, width, height,
2575 core_clk, dispc_core_clk_rate(dispc));
2577 if (!core_clk || core_clk > dispc_core_clk_rate(dispc)) {
2581 core_clk, dispc_core_clk_rate(dispc));
2590 static int dispc_ovl_setup_common(struct dispc_device *dispc,
2615 unsigned long pclk = dispc_plane_pclk_rate(dispc, plane);
2616 unsigned long lclk = dispc_plane_lclk_rate(dispc, plane);
2651 if (!dispc_ovl_color_mode_supported(dispc, plane, fourcc))
2654 r = dispc_ovl_calc_scaling(dispc, plane, pclk, lclk, caps, vm, in_width,
2716 dispc_ovl_set_color_mode(dispc, plane, fourcc);
2718 dispc_ovl_configure_burst_type(dispc, plane, rotation_type);
2720 if (dispc->feat->reverse_ilace_field_order)
2723 dispc_ovl_set_ba0(dispc, plane, paddr + offset0);
2724 dispc_ovl_set_ba1(dispc, plane, paddr + offset1);
2727 dispc_ovl_set_ba0_uv(dispc, plane, p_uv_addr + offset0);
2728 dispc_ovl_set_ba1_uv(dispc, plane, p_uv_addr + offset1);
2731 if (dispc->feat->last_pixel_inc_missing)
2734 dispc_ovl_set_row_inc(dispc, plane, row_inc);
2735 dispc_ovl_set_pix_inc(dispc, plane, pix_inc);
2740 dispc_ovl_set_pos(dispc, plane, caps, pos_x, pos_y);
2742 dispc_ovl_set_input_size(dispc, plane, in_width, in_height);
2745 dispc_ovl_set_scaling(dispc, plane, in_width, in_height,
2748 dispc_ovl_set_output_size(dispc, plane, out_width, out_height);
2749 dispc_ovl_set_vid_color_conv(dispc, plane, cconv);
2752 dispc_ovl_set_rotation_attrs(dispc, plane, rotation, rotation_type,
2755 dispc_ovl_set_zorder(dispc, plane, caps, zorder);
2756 dispc_ovl_set_pre_mult_alpha(dispc, plane, caps, pre_mult_alpha);
2757 dispc_ovl_setup_global_alpha(dispc, plane, caps, global_alpha);
2759 dispc_ovl_enable_replication(dispc, plane, caps, replication);
2764 static int dispc_ovl_setup(struct dispc_device *dispc,
2771 enum omap_overlay_caps caps = dispc->feat->overlay_caps[plane];
2780 dispc_ovl_set_channel_out(dispc, plane, channel);
2782 r = dispc_ovl_setup_common(dispc, plane, caps, oi->paddr, oi->p_uv_addr,
2791 static int dispc_wb_setup(struct dispc_device *dispc,
2815 r = dispc_ovl_setup_common(dispc, plane, caps, wi->paddr, wi->p_uv_addr,
2840 l = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
2848 dispc_write_reg(dispc, DISPC_OVL_ATTRIBUTES(plane), l);
2852 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane), 0, 7, 0);
2868 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane), wbdelay, 7, 0);
2874 static bool dispc_has_writeback(struct dispc_device *dispc)
2876 return dispc->feat->has_writeback;
2879 static int dispc_ovl_enable(struct dispc_device *dispc,
2884 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
2889 static void dispc_lcd_enable_signal_polarity(struct dispc_device *dispc,
2892 if (!dispc_has_feature(dispc, FEAT_LCDENABLEPOL))
2895 REG_FLD_MOD(dispc, DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
2898 void dispc_lcd_enable_signal(struct dispc_device *dispc, bool enable)
2900 if (!dispc_has_feature(dispc, FEAT_LCDENABLESIGNAL))
2903 REG_FLD_MOD(dispc, DISPC_CONTROL, enable ? 1 : 0, 28, 28);
2906 void dispc_pck_free_enable(struct dispc_device *dispc, bool enable)
2908 if (!dispc_has_feature(dispc, FEAT_PCKFREEENABLE))
2911 REG_FLD_MOD(dispc, DISPC_CONTROL, enable ? 1 : 0, 27, 27);
2914 static void dispc_mgr_enable_fifohandcheck(struct dispc_device *dispc,
2918 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
2922 static void dispc_mgr_set_lcd_type_tft(struct dispc_device *dispc,
2925 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_STNTFT, 1);
2928 static void dispc_set_loadmode(struct dispc_device *dispc,
2931 REG_FLD_MOD(dispc, DISPC_CONFIG, mode, 2, 1);
2935 static void dispc_mgr_set_default_color(struct dispc_device *dispc,
2938 dispc_write_reg(dispc, DISPC_DEFAULT_COLOR(channel), color);
2941 static void dispc_mgr_set_trans_key(struct dispc_device *dispc,
2946 mgr_fld_write(dispc, ch, DISPC_MGR_FLD_TCKSELECTION, type);
2948 dispc_write_reg(dispc, DISPC_TRANS_COLOR(ch), trans_key);
2951 static void dispc_mgr_enable_trans_key(struct dispc_device *dispc,
2954 mgr_fld_write(dispc, ch, DISPC_MGR_FLD_TCKENABLE, enable);
2957 static void dispc_mgr_enable_alpha_fixed_zorder(struct dispc_device *dispc,
2961 if (!dispc_has_feature(dispc, FEAT_ALPHA_FIXED_ZORDER))
2965 REG_FLD_MOD(dispc, DISPC_CONFIG, enable, 18, 18);
2967 REG_FLD_MOD(dispc, DISPC_CONFIG, enable, 19, 19);
2970 static void dispc_mgr_setup(struct dispc_device *dispc,
2974 dispc_mgr_set_default_color(dispc, channel, info->default_color);
2975 dispc_mgr_set_trans_key(dispc, channel, info->trans_key_type,
2977 dispc_mgr_enable_trans_key(dispc, channel, info->trans_enabled);
2978 dispc_mgr_enable_alpha_fixed_zorder(dispc, channel,
2980 if (dispc_has_feature(dispc, FEAT_CPR)) {
2981 dispc_mgr_enable_cpr(dispc, channel, info->cpr_enable);
2982 dispc_mgr_set_cpr_coef(dispc, channel, &info->cpr_coefs);
2986 static void dispc_mgr_set_tft_data_lines(struct dispc_device *dispc,
3010 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_TFTDATALINES, code);
3013 static void dispc_mgr_set_io_pad_mode(struct dispc_device *dispc,
3037 l = dispc_read_reg(dispc, DISPC_CONTROL);
3040 dispc_write_reg(dispc, DISPC_CONTROL, l);
3043 static void dispc_mgr_enable_stallmode(struct dispc_device *dispc,
3046 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_STALLMODE, enable);
3049 static void dispc_mgr_set_lcd_config(struct dispc_device *dispc,
3053 dispc_mgr_set_io_pad_mode(dispc, config->io_pad_mode);
3055 dispc_mgr_enable_stallmode(dispc, channel, config->stallmode);
3056 dispc_mgr_enable_fifohandcheck(dispc, channel, config->fifohandcheck);
3058 dispc_mgr_set_clock_div(dispc, channel, &config->clock_info);
3060 dispc_mgr_set_tft_data_lines(dispc, channel, config->video_port_width);
3062 dispc_lcd_enable_signal_polarity(dispc, config->lcden_sig_polarity);
3064 dispc_mgr_set_lcd_type_tft(dispc, channel);
3067 static bool _dispc_mgr_size_ok(struct dispc_device *dispc,
3070 return width <= dispc->feat->mgr_width_max &&
3071 height <= dispc->feat->mgr_height_max;
3074 static bool _dispc_lcd_timings_ok(struct dispc_device *dispc,
3078 if (hsync_len < 1 || hsync_len > dispc->feat->sw_max ||
3079 hfp < 1 || hfp > dispc->feat->hp_max ||
3080 hbp < 1 || hbp > dispc->feat->hp_max ||
3081 vsw < 1 || vsw > dispc->feat->sw_max ||
3082 vfp < 0 || vfp > dispc->feat->vp_max ||
3083 vbp < 0 || vbp > dispc->feat->vp_max)
3088 static bool _dispc_mgr_pclk_ok(struct dispc_device *dispc,
3093 return pclk <= dispc->feat->max_lcd_pclk;
3095 return pclk <= dispc->feat->max_tv_pclk;
3098 static int dispc_mgr_check_timings(struct dispc_device *dispc,
3102 if (!_dispc_mgr_size_ok(dispc, vm->hactive, vm->vactive))
3105 if (!_dispc_mgr_pclk_ok(dispc, channel, vm->pixelclock))
3113 if (!_dispc_lcd_timings_ok(dispc, vm->hsync_len,
3123 static void _dispc_mgr_set_lcd_timings(struct dispc_device *dispc,
3130 timing_h = FLD_VAL(vm->hsync_len - 1, dispc->feat->sw_start, 0) |
3131 FLD_VAL(vm->hfront_porch - 1, dispc->feat->fp_start, 8) |
3132 FLD_VAL(vm->hback_porch - 1, dispc->feat->bp_start, 20);
3133 timing_v = FLD_VAL(vm->vsync_len - 1, dispc->feat->sw_start, 0) |
3134 FLD_VAL(vm->vfront_porch, dispc->feat->fp_start, 8) |
3135 FLD_VAL(vm->vback_porch, dispc->feat->bp_start, 20);
3137 dispc_write_reg(dispc, DISPC_TIMING_H(channel), timing_h);
3138 dispc_write_reg(dispc, DISPC_TIMING_V(channel), timing_v);
3155 if (dispc->feat->supports_sync_align)
3158 dispc_write_reg(dispc, DISPC_POL_FREQ(channel), l);
3160 if (dispc->syscon_pol) {
3175 regmap_update_bits(dispc->syscon_pol, dispc->syscon_pol_offset,
3191 static void dispc_mgr_set_timings(struct dispc_device *dispc,
3201 if (dispc_mgr_check_timings(dispc, channel, &t)) {
3207 _dispc_mgr_set_lcd_timings(dispc, channel, &t);
3231 if (dispc->feat->supports_double_pixel)
3232 REG_FLD_MOD(dispc, DISPC_CONTROL,
3237 dispc_mgr_set_size(dispc, channel, t.hactive, t.vactive);
3240 static void dispc_mgr_set_lcd_divisor(struct dispc_device *dispc,
3247 dispc_write_reg(dispc, DISPC_DIVISORo(channel),
3250 if (!dispc_has_feature(dispc, FEAT_CORE_CLK_DIV) &&
3252 dispc->core_clk_rate = dispc_fclk_rate(dispc) / lck_div;
3255 static void dispc_mgr_get_lcd_divisor(struct dispc_device *dispc,
3260 l = dispc_read_reg(dispc, DISPC_DIVISORo(channel));
3265 static unsigned long dispc_fclk_rate(struct dispc_device *dispc)
3270 src = dss_get_dispc_clk_source(dispc->dss);
3273 r = dss_get_dispc_clk_rate(dispc->dss);
3278 pll = dss_pll_find_by_src(dispc->dss, src);
3287 static unsigned long dispc_mgr_lclk_rate(struct dispc_device *dispc,
3296 return dispc_fclk_rate(dispc);
3298 src = dss_get_lcd_clk_source(dispc->dss, channel);
3301 r = dss_get_dispc_clk_rate(dispc->dss);
3306 pll = dss_pll_find_by_src(dispc->dss, src);
3312 lcd = REG_GET(dispc, DISPC_DIVISORo(channel), 23, 16);
3317 static unsigned long dispc_mgr_pclk_rate(struct dispc_device *dispc,
3326 l = dispc_read_reg(dispc, DISPC_DIVISORo(channel));
3330 r = dispc_mgr_lclk_rate(dispc, channel);
3334 return dispc->tv_pclk_rate;
3338 void dispc_set_tv_pclk(struct dispc_device *dispc, unsigned long pclk)
3340 dispc->tv_pclk_rate = pclk;
3343 static unsigned long dispc_core_clk_rate(struct dispc_device *dispc)
3345 return dispc->core_clk_rate;
3348 static unsigned long dispc_plane_pclk_rate(struct dispc_device *dispc,
3356 channel = dispc_ovl_get_channel_out(dispc, plane);
3358 return dispc_mgr_pclk_rate(dispc, channel);
3361 static unsigned long dispc_plane_lclk_rate(struct dispc_device *dispc,
3369 channel = dispc_ovl_get_channel_out(dispc, plane);
3371 return dispc_mgr_lclk_rate(dispc, channel);
3374 static void dispc_dump_clocks_channel(struct dispc_device *dispc,
3383 lcd_clk_src = dss_get_lcd_clk_source(dispc->dss, channel);
3388 dispc_mgr_get_lcd_divisor(dispc, channel, &lcd, &pcd);
3391 dispc_mgr_lclk_rate(dispc, channel), lcd);
3393 dispc_mgr_pclk_rate(dispc, channel), pcd);
3396 void dispc_dump_clocks(struct dispc_device *dispc, struct seq_file *s)
3402 if (dispc_runtime_get(dispc))
3407 dispc_clk_src = dss_get_dispc_clk_source(dispc->dss);
3408 seq_printf(s, "dispc fclk source = %s\n",
3411 seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate(dispc));
3413 if (dispc_has_feature(dispc, FEAT_CORE_CLK_DIV)) {
3415 l = dispc_read_reg(dispc, DISPC_DIVISOR);
3419 (dispc_fclk_rate(dispc)/lcd), lcd);
3422 dispc_dump_clocks_channel(dispc, s, OMAP_DSS_CHANNEL_LCD);
3424 if (dispc_has_feature(dispc, FEAT_MGR_LCD2))
3425 dispc_dump_clocks_channel(dispc, s, OMAP_DSS_CHANNEL_LCD2);
3426 if (dispc_has_feature(dispc, FEAT_MGR_LCD3))
3427 dispc_dump_clocks_channel(dispc, s, OMAP_DSS_CHANNEL_LCD3);
3429 dispc_runtime_put(dispc);
3434 struct dispc_device *dispc = s->private;
3451 #define DUMPREG(dispc, r) \
3452 seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(dispc, r))
3454 if (dispc_runtime_get(dispc))
3458 DUMPREG(dispc, DISPC_REVISION);
3459 DUMPREG(dispc, DISPC_SYSCONFIG);
3460 DUMPREG(dispc, DISPC_SYSSTATUS);
3461 DUMPREG(dispc, DISPC_IRQSTATUS);
3462 DUMPREG(dispc, DISPC_IRQENABLE);
3463 DUMPREG(dispc, DISPC_CONTROL);
3464 DUMPREG(dispc, DISPC_CONFIG);
3465 DUMPREG(dispc, DISPC_CAPABLE);
3466 DUMPREG(dispc, DISPC_LINE_STATUS);
3467 DUMPREG(dispc, DISPC_LINE_NUMBER);
3468 if (dispc_has_feature(dispc, FEAT_ALPHA_FIXED_ZORDER) ||
3469 dispc_has_feature(dispc, FEAT_ALPHA_FREE_ZORDER))
3470 DUMPREG(dispc, DISPC_GLOBAL_ALPHA);
3471 if (dispc_has_feature(dispc, FEAT_MGR_LCD2)) {
3472 DUMPREG(dispc, DISPC_CONTROL2);
3473 DUMPREG(dispc, DISPC_CONFIG2);
3475 if (dispc_has_feature(dispc, FEAT_MGR_LCD3)) {
3476 DUMPREG(dispc, DISPC_CONTROL3);
3477 DUMPREG(dispc, DISPC_CONFIG3);
3479 if (dispc_has_feature(dispc, FEAT_MFLAG))
3480 DUMPREG(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE);
3485 #define DUMPREG(dispc, i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
3487 dispc_read_reg(dispc, DISPC_REG(i, r)))
3492 for (i = 0; i < dispc_get_num_mgrs(dispc); i++) {
3493 DUMPREG(dispc, i, DISPC_DEFAULT_COLOR);
3494 DUMPREG(dispc, i, DISPC_TRANS_COLOR);
3495 DUMPREG(dispc, i, DISPC_SIZE_MGR);
3500 DUMPREG(dispc, i, DISPC_TIMING_H);
3501 DUMPREG(dispc, i, DISPC_TIMING_V);
3502 DUMPREG(dispc, i, DISPC_POL_FREQ);
3503 DUMPREG(dispc, i, DISPC_DIVISORo);
3505 DUMPREG(dispc, i, DISPC_DATA_CYCLE1);
3506 DUMPREG(dispc, i, DISPC_DATA_CYCLE2);
3507 DUMPREG(dispc, i, DISPC_DATA_CYCLE3);
3509 if (dispc_has_feature(dispc, FEAT_CPR)) {
3510 DUMPREG(dispc, i, DISPC_CPR_COEF_R);
3511 DUMPREG(dispc, i, DISPC_CPR_COEF_G);
3512 DUMPREG(dispc, i, DISPC_CPR_COEF_B);
3518 for (i = 0; i < dispc_get_num_ovls(dispc); i++) {
3519 DUMPREG(dispc, i, DISPC_OVL_BA0);
3520 DUMPREG(dispc, i, DISPC_OVL_BA1);
3521 DUMPREG(dispc, i, DISPC_OVL_POSITION);
3522 DUMPREG(dispc, i, DISPC_OVL_SIZE);
3523 DUMPREG(dispc, i, DISPC_OVL_ATTRIBUTES);
3524 DUMPREG(dispc, i, DISPC_OVL_FIFO_THRESHOLD);
3525 DUMPREG(dispc, i, DISPC_OVL_FIFO_SIZE_STATUS);
3526 DUMPREG(dispc, i, DISPC_OVL_ROW_INC);
3527 DUMPREG(dispc, i, DISPC_OVL_PIXEL_INC);
3529 if (dispc_has_feature(dispc, FEAT_PRELOAD))
3530 DUMPREG(dispc, i, DISPC_OVL_PRELOAD);
3531 if (dispc_has_feature(dispc, FEAT_MFLAG))
3532 DUMPREG(dispc, i, DISPC_OVL_MFLAG_THRESHOLD);
3535 DUMPREG(dispc, i, DISPC_OVL_WINDOW_SKIP);
3536 DUMPREG(dispc, i, DISPC_OVL_TABLE_BA);
3540 DUMPREG(dispc, i, DISPC_OVL_FIR);
3541 DUMPREG(dispc, i, DISPC_OVL_PICTURE_SIZE);
3542 DUMPREG(dispc, i, DISPC_OVL_ACCU0);
3543 DUMPREG(dispc, i, DISPC_OVL_ACCU1);
3544 if (dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE)) {
3545 DUMPREG(dispc, i, DISPC_OVL_BA0_UV);
3546 DUMPREG(dispc, i, DISPC_OVL_BA1_UV);
3547 DUMPREG(dispc, i, DISPC_OVL_FIR2);
3548 DUMPREG(dispc, i, DISPC_OVL_ACCU2_0);
3549 DUMPREG(dispc, i, DISPC_OVL_ACCU2_1);
3551 if (dispc_has_feature(dispc, FEAT_ATTR2))
3552 DUMPREG(dispc, i, DISPC_OVL_ATTRIBUTES2);
3555 if (dispc->feat->has_writeback) {
3557 DUMPREG(dispc, i, DISPC_OVL_BA0);
3558 DUMPREG(dispc, i, DISPC_OVL_BA1);
3559 DUMPREG(dispc, i, DISPC_OVL_SIZE);
3560 DUMPREG(dispc, i, DISPC_OVL_ATTRIBUTES);
3561 DUMPREG(dispc, i, DISPC_OVL_FIFO_THRESHOLD);
3562 DUMPREG(dispc, i, DISPC_OVL_FIFO_SIZE_STATUS);
3563 DUMPREG(dispc, i, DISPC_OVL_ROW_INC);
3564 DUMPREG(dispc, i, DISPC_OVL_PIXEL_INC);
3566 if (dispc_has_feature(dispc, FEAT_MFLAG))
3567 DUMPREG(dispc, i, DISPC_OVL_MFLAG_THRESHOLD);
3569 DUMPREG(dispc, i, DISPC_OVL_FIR);
3570 DUMPREG(dispc, i, DISPC_OVL_PICTURE_SIZE);
3571 DUMPREG(dispc, i, DISPC_OVL_ACCU0);
3572 DUMPREG(dispc, i, DISPC_OVL_ACCU1);
3573 if (dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE)) {
3574 DUMPREG(dispc, i, DISPC_OVL_BA0_UV);
3575 DUMPREG(dispc, i, DISPC_OVL_BA1_UV);
3576 DUMPREG(dispc, i, DISPC_OVL_FIR2);
3577 DUMPREG(dispc, i, DISPC_OVL_ACCU2_0);
3578 DUMPREG(dispc, i, DISPC_OVL_ACCU2_1);
3580 if (dispc_has_feature(dispc, FEAT_ATTR2))
3581 DUMPREG(dispc, i, DISPC_OVL_ATTRIBUTES2);
3588 #define DUMPREG(dispc, plane, name, i) \
3591 dispc_read_reg(dispc, DISPC_REG(plane, name, i)))
3596 for (i = 1; i < dispc_get_num_ovls(dispc); i++) {
3598 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_H, j);
3601 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_HV, j);
3604 DUMPREG(dispc, i, DISPC_OVL_CONV_COEF, j);
3606 if (dispc_has_feature(dispc, FEAT_FIR_COEF_V)) {
3608 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_V, j);
3611 if (dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE)) {
3613 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_H2, j);
3616 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_HV2, j);
3619 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_V2, j);
3623 dispc_runtime_put(dispc);
3632 int dispc_calc_clock_rates(struct dispc_device *dispc,
3647 bool dispc_div_calc(struct dispc_device *dispc, unsigned long dispc_freq,
3665 pckd_hw_min = dispc->feat->min_pcd;
3668 lck_max = dss_get_max_fck_rate(dispc->dss);
3691 if (dispc_has_feature(dispc, FEAT_CORE_CLK_DIV))
3692 fck = dispc_core_clk_rate(dispc);
3707 void dispc_mgr_set_clock_div(struct dispc_device *dispc,
3714 dispc_mgr_set_lcd_divisor(dispc, channel, cinfo->lck_div,
3718 int dispc_mgr_get_clock_div(struct dispc_device *dispc,
3724 fck = dispc_fclk_rate(dispc);
3726 cinfo->lck_div = REG_GET(dispc, DISPC_DIVISORo(channel), 23, 16);
3727 cinfo->pck_div = REG_GET(dispc, DISPC_DIVISORo(channel), 7, 0);
3735 static u32 dispc_read_irqstatus(struct dispc_device *dispc)
3737 return dispc_read_reg(dispc, DISPC_IRQSTATUS);
3740 static void dispc_clear_irqstatus(struct dispc_device *dispc, u32 mask)
3742 dispc_write_reg(dispc, DISPC_IRQSTATUS, mask);
3745 static void dispc_write_irqenable(struct dispc_device *dispc, u32 mask)
3747 u32 old_mask = dispc_read_reg(dispc, DISPC_IRQENABLE);
3750 dispc_clear_irqstatus(dispc, (mask ^ old_mask) & mask);
3752 dispc_write_reg(dispc, DISPC_IRQENABLE, mask);
3755 dispc_read_reg(dispc, DISPC_IRQENABLE);
3758 void dispc_enable_sidle(struct dispc_device *dispc)
3761 REG_FLD_MOD(dispc, DISPC_SYSCONFIG, 2, 4, 3);
3764 void dispc_disable_sidle(struct dispc_device *dispc)
3766 REG_FLD_MOD(dispc, DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
3769 static u32 dispc_mgr_gamma_size(struct dispc_device *dispc,
3774 if (!dispc->feat->has_gamma_table)
3780 static void dispc_mgr_write_gamma_table(struct dispc_device *dispc,
3784 u32 *table = dispc->gamma_table[channel];
3797 dispc_write_reg(dispc, gdesc->reg, v);
3801 static void dispc_restore_gamma_tables(struct dispc_device *dispc)
3805 if (!dispc->feat->has_gamma_table)
3808 dispc_mgr_write_gamma_table(dispc, OMAP_DSS_CHANNEL_LCD);
3810 dispc_mgr_write_gamma_table(dispc, OMAP_DSS_CHANNEL_DIGIT);
3812 if (dispc_has_feature(dispc, FEAT_MGR_LCD2))
3813 dispc_mgr_write_gamma_table(dispc, OMAP_DSS_CHANNEL_LCD2);
3815 if (dispc_has_feature(dispc, FEAT_MGR_LCD3))
3816 dispc_mgr_write_gamma_table(dispc, OMAP_DSS_CHANNEL_LCD3);
3824 static void dispc_mgr_set_gamma(struct dispc_device *dispc,
3830 u32 *table = dispc->gamma_table[channel];
3836 if (!dispc->feat->has_gamma_table)
3868 if (dispc->is_enabled)
3869 dispc_mgr_write_gamma_table(dispc, channel);
3872 static int dispc_init_gamma_tables(struct dispc_device *dispc)
3876 if (!dispc->feat->has_gamma_table)
3879 for (channel = 0; channel < ARRAY_SIZE(dispc->gamma_table); channel++) {
3884 !dispc_has_feature(dispc, FEAT_MGR_LCD2))
3888 !dispc_has_feature(dispc, FEAT_MGR_LCD3))
3891 gt = devm_kmalloc_array(&dispc->pdev->dev, gdesc->len,
3896 dispc->gamma_table[channel] = gt;
3898 dispc_mgr_set_gamma(dispc, channel, NULL, 0);
3903 static void _omap_dispc_initial_config(struct dispc_device *dispc)
3908 if (dispc_has_feature(dispc, FEAT_CORE_CLK_DIV)) {
3909 l = dispc_read_reg(dispc, DISPC_DIVISOR);
3913 dispc_write_reg(dispc, DISPC_DIVISOR, l);
3915 dispc->core_clk_rate = dispc_fclk_rate(dispc);
3919 if (dispc->feat->has_gamma_table)
3920 REG_FLD_MOD(dispc, DISPC_CONFIG, 1, 3, 3);
3924 * (dispc->feat->has_gamma_table) this enables tv-out gamma tables.
3926 if (dispc_has_feature(dispc, FEAT_FUNCGATED) ||
3927 dispc->feat->has_gamma_table)
3928 REG_FLD_MOD(dispc, DISPC_CONFIG, 1, 9, 9);
3930 dispc_setup_color_conv_coef(dispc);
3932 dispc_set_loadmode(dispc, OMAP_DSS_LOAD_FRAME_ONLY);
3934 dispc_init_fifos(dispc);
3936 dispc_configure_burst_sizes(dispc);
3938 dispc_ovl_enable_zorder_planes(dispc);
3940 if (dispc->feat->mstandby_workaround)
3941 REG_FLD_MOD(dispc, DISPC_MSTANDBY_CTRL, 1, 0, 0);
3943 if (dispc_has_feature(dispc, FEAT_MFLAG))
3944 dispc_init_mflag(dispc);
4474 struct dispc_device *dispc = arg;
4476 if (!dispc->is_enabled)
4479 return dispc->user_handler(irq, dispc->user_data);
4482 static int dispc_request_irq(struct dispc_device *dispc, irq_handler_t handler,
4487 if (dispc->user_handler != NULL)
4490 dispc->user_handler = handler;
4491 dispc->user_data = dev_id;
4496 r = devm_request_irq(&dispc->pdev->dev, dispc->irq, dispc_irq_handler,
4497 IRQF_SHARED, "OMAP DISPC", dispc);
4499 dispc->user_handler = NULL;
4500 dispc->user_data = NULL;
4506 static void dispc_free_irq(struct dispc_device *dispc, void *dev_id)
4508 devm_free_irq(&dispc->pdev->dev, dispc->irq, dispc);
4510 dispc->user_handler = NULL;
4511 dispc->user_data = NULL;
4514 static u32 dispc_get_memory_bandwidth_limit(struct dispc_device *dispc)
4519 of_property_read_u32(dispc->pdev->dev.of_node, "max-memory-bandwidth",
4526 * Workaround for errata i734 in DSS dispc
4596 static int dispc_errata_i734_wa_init(struct dispc_device *dispc)
4598 if (!dispc->feat->has_gamma_i734_bug)
4604 i734_buf.vaddr = dma_alloc_wc(&dispc->pdev->dev, i734_buf.size,
4607 dev_err(&dispc->pdev->dev, "%s: dma_alloc_wc failed\n",
4615 static void dispc_errata_i734_wa_fini(struct dispc_device *dispc)
4617 if (!dispc->feat->has_gamma_i734_bug)
4620 dma_free_wc(&dispc->pdev->dev, i734_buf.size, i734_buf.vaddr,
4624 static void dispc_errata_i734_wa(struct dispc_device *dispc)
4626 u32 framedone_irq = dispc_mgr_get_framedone_irq(dispc,
4633 if (!dispc->feat->has_gamma_i734_bug)
4636 gatestate = REG_GET(dispc, DISPC_CONFIG, 8, 4);
4643 REG_FLD_MOD(dispc, DISPC_CONFIG, 0x1f, 8, 4);
4646 dispc_ovl_setup(dispc, OMAP_DSS_GFX, &ovli, &i734.vm, false,
4648 dispc_ovl_enable(dispc, OMAP_DSS_GFX, true);
4651 dispc_mgr_setup(dispc, OMAP_DSS_CHANNEL_LCD, &i734.mgri);
4652 dispc_calc_clock_rates(dispc, dss_get_dispc_clk_rate(dispc->dss),
4654 dispc_mgr_set_lcd_config(dispc, OMAP_DSS_CHANNEL_LCD, &lcd_conf);
4655 dispc_mgr_set_timings(dispc, OMAP_DSS_CHANNEL_LCD, &i734.vm);
4657 dispc_clear_irqstatus(dispc, framedone_irq);
4660 dispc_mgr_enable(dispc, OMAP_DSS_CHANNEL_LCD, true);
4661 dispc_mgr_enable(dispc, OMAP_DSS_CHANNEL_LCD, false);
4668 while (!(dispc_read_irqstatus(dispc) & framedone_irq)) {
4670 dev_err(&dispc->pdev->dev, "%s: framedone timeout\n",
4675 dispc_ovl_enable(dispc, OMAP_DSS_GFX, false);
4678 dispc_clear_irqstatus(dispc, 0xffffffff);
4681 REG_FLD_MOD(dispc, DISPC_CONFIG, gatestate, 8, 4);
4727 { .compatible = "ti,omap2-dispc", .data = &omap24xx_dispc_feats },
4728 { .compatible = "ti,omap3-dispc", .data = &omap36xx_dispc_feats },
4729 { .compatible = "ti,omap4-dispc", .data = &omap44xx_dispc_feats },
4730 { .compatible = "ti,omap5-dispc", .data = &omap54xx_dispc_feats },
4731 { .compatible = "ti,dra7-dispc", .data = &omap54xx_dispc_feats },
4749 struct dispc_device *dispc;
4755 dispc = kzalloc(sizeof(*dispc), GFP_KERNEL);
4756 if (!dispc)
4759 dispc->pdev = pdev;
4760 platform_set_drvdata(pdev, dispc);
4761 dispc->dss = dss;
4769 dispc->feat = soc->data;
4771 dispc->feat = of_match_device(dispc_of_match, &pdev->dev)->data;
4773 r = dispc_errata_i734_wa_init(dispc);
4777 dispc_mem = platform_get_resource(dispc->pdev, IORESOURCE_MEM, 0);
4778 dispc->base = devm_ioremap_resource(&pdev->dev, dispc_mem);
4779 if (IS_ERR(dispc->base)) {
4780 r = PTR_ERR(dispc->base);
4784 dispc->irq = platform_get_irq(dispc->pdev, 0);
4785 if (dispc->irq < 0) {
4792 dispc->syscon_pol = syscon_regmap_lookup_by_phandle(np, "syscon-pol");
4793 if (IS_ERR(dispc->syscon_pol)) {
4795 r = PTR_ERR(dispc->syscon_pol);
4800 &dispc->syscon_pol_offset)) {
4807 r = dispc_init_gamma_tables(dispc);
4813 r = dispc_runtime_get(dispc);
4817 _omap_dispc_initial_config(dispc);
4819 rev = dispc_read_reg(dispc, DISPC_REVISION);
4823 dispc_runtime_put(dispc);
4825 dss->dispc = dispc;
4828 dispc->debugfs = dss_debugfs_create_file(dss, "dispc", dispc_dump_regs,
4829 dispc);
4836 kfree(dispc);
4842 struct dispc_device *dispc = dev_get_drvdata(dev);
4843 struct dss_device *dss = dispc->dss;
4845 dss_debugfs_remove_file(dispc->debugfs);
4847 dss->dispc = NULL;
4852 dispc_errata_i734_wa_fini(dispc);
4854 kfree(dispc);
4875 struct dispc_device *dispc = dev_get_drvdata(dev);
4877 dispc->is_enabled = false;
4881 synchronize_irq(dispc->irq);
4883 dispc_save_context(dispc);
4890 struct dispc_device *dispc = dev_get_drvdata(dev);
4898 if (REG_GET(dispc, DISPC_CONFIG, 2, 1) != OMAP_DSS_LOAD_FRAME_ONLY) {
4899 _omap_dispc_initial_config(dispc);
4901 dispc_errata_i734_wa(dispc);
4903 dispc_restore_context(dispc);
4905 dispc_restore_gamma_tables(dispc);
4908 dispc->is_enabled = true;