Lines Matching defs: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 noinline_for_stack 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 void dispc_mgr_enable(struct dispc_device *dispc,
697 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_ENABLE, enable);
699 mgr_fld_read(dispc, channel, DISPC_MGR_FLD_ENABLE);
702 static bool dispc_mgr_is_enabled(struct dispc_device *dispc,
705 return !!mgr_fld_read(dispc, channel, DISPC_MGR_FLD_ENABLE);
708 bool dispc_mgr_go_busy(struct dispc_device *dispc,
711 return mgr_fld_read(dispc, channel, DISPC_MGR_FLD_GO) == 1;
714 void dispc_mgr_go(struct dispc_device *dispc, enum omap_channel channel)
716 WARN_ON(!dispc_mgr_is_enabled(dispc, channel));
717 WARN_ON(dispc_mgr_go_busy(dispc, channel));
721 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_GO, 1);
724 static void dispc_ovl_write_firh_reg(struct dispc_device *dispc,
728 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_H(plane, reg), value);
731 static void dispc_ovl_write_firhv_reg(struct dispc_device *dispc,
735 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_HV(plane, reg), value);
738 static void dispc_ovl_write_firv_reg(struct dispc_device *dispc,
742 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_V(plane, reg), value);
745 static void dispc_ovl_write_firh2_reg(struct dispc_device *dispc,
751 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_H2(plane, reg), value);
754 static void dispc_ovl_write_firhv2_reg(struct dispc_device *dispc,
760 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_HV2(plane, reg), value);
763 static void dispc_ovl_write_firv2_reg(struct dispc_device *dispc,
769 dispc_write_reg(dispc, DISPC_OVL_FIR_COEF_V2(plane, reg), value);
772 static void dispc_ovl_set_scale_coef(struct dispc_device *dispc,
784 dev_err(&dispc->pdev->dev, "%s: failed to find scale coefs\n",
802 dispc_ovl_write_firh_reg(dispc, plane, i, h);
803 dispc_ovl_write_firhv_reg(dispc, plane, i, hv);
805 dispc_ovl_write_firh2_reg(dispc, plane, i, h);
806 dispc_ovl_write_firhv2_reg(dispc, plane, i, hv);
817 dispc_ovl_write_firv_reg(dispc, plane, i, v);
819 dispc_ovl_write_firv2_reg(dispc, plane, i, v);
829 static void dispc_ovl_write_color_conv_coef(struct dispc_device *dispc,
835 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry));
836 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy, ct->rcb));
837 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr));
838 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by));
839 dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb));
841 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);
878 static void dispc_ovl_set_csc(struct dispc_device *dispc,
901 dispc_ovl_write_color_conv_coef(dispc, plane, csc);
904 static void dispc_ovl_set_ba0(struct dispc_device *dispc,
907 dispc_write_reg(dispc, DISPC_OVL_BA0(plane), paddr);
910 static void dispc_ovl_set_ba1(struct dispc_device *dispc,
913 dispc_write_reg(dispc, DISPC_OVL_BA1(plane), paddr);
916 static void dispc_ovl_set_ba0_uv(struct dispc_device *dispc,
919 dispc_write_reg(dispc, DISPC_OVL_BA0_UV(plane), paddr);
922 static void dispc_ovl_set_ba1_uv(struct dispc_device *dispc,
925 dispc_write_reg(dispc, DISPC_OVL_BA1_UV(plane), paddr);
928 static void dispc_ovl_set_pos(struct dispc_device *dispc,
939 dispc_write_reg(dispc, DISPC_OVL_POSITION(plane), val);
942 static void dispc_ovl_set_input_size(struct dispc_device *dispc,
949 dispc_write_reg(dispc, DISPC_OVL_SIZE(plane), val);
951 dispc_write_reg(dispc, DISPC_OVL_PICTURE_SIZE(plane), val);
954 static void dispc_ovl_set_output_size(struct dispc_device *dispc,
965 dispc_write_reg(dispc, DISPC_OVL_PICTURE_SIZE(plane), val);
967 dispc_write_reg(dispc, DISPC_OVL_SIZE(plane), val);
970 static void dispc_ovl_set_zorder(struct dispc_device *dispc,
977 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
980 static void dispc_ovl_enable_zorder_planes(struct dispc_device *dispc)
984 if (!dispc_has_feature(dispc, FEAT_ALPHA_FREE_ZORDER))
987 for (i = 0; i < dispc_get_num_ovls(dispc); i++)
988 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
991 static void dispc_ovl_set_pre_mult_alpha(struct dispc_device *dispc,
999 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
1002 static void dispc_ovl_setup_global_alpha(struct dispc_device *dispc,
1014 REG_FLD_MOD(dispc, DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift);
1017 static void dispc_ovl_set_pix_inc(struct dispc_device *dispc,
1020 dispc_write_reg(dispc, DISPC_OVL_PIXEL_INC(plane), inc);
1023 static void dispc_ovl_set_row_inc(struct dispc_device *dispc,
1026 dispc_write_reg(dispc, DISPC_OVL_ROW_INC(plane), inc);
1029 static void dispc_ovl_set_color_mode(struct dispc_device *dispc,
1099 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
1102 static void dispc_ovl_configure_burst_type(struct dispc_device *dispc,
1106 if (dispc_has_feature(dispc, FEAT_BURST_2D) == 0)
1110 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), 1, 29, 29);
1112 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), 0, 29, 29);
1115 static void dispc_ovl_set_channel_out(struct dispc_device *dispc,
1137 val = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
1138 if (dispc_has_feature(dispc, FEAT_MGR_LCD2)) {
1153 if (dispc_has_feature(dispc, FEAT_MGR_LCD3)) {
1175 dispc_write_reg(dispc, DISPC_OVL_ATTRIBUTES(plane), val);
1178 static enum omap_channel dispc_ovl_get_channel_out(struct dispc_device *dispc,
1198 val = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
1203 if (!dispc_has_feature(dispc, FEAT_MGR_LCD2))
1219 static void dispc_ovl_set_burst_size(struct dispc_device *dispc,
1227 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), burst_size,
1231 static void dispc_configure_burst_sizes(struct dispc_device *dispc)
1237 for (i = 0; i < dispc_get_num_ovls(dispc); ++i)
1238 dispc_ovl_set_burst_size(dispc, i, burst_size);
1239 if (dispc->feat->has_writeback)
1240 dispc_ovl_set_burst_size(dispc, OMAP_DSS_WB, burst_size);
1243 static u32 dispc_ovl_get_burst_size(struct dispc_device *dispc,
1247 return dispc->feat->burst_size_unit * 8;
1250 bool dispc_ovl_color_mode_supported(struct dispc_device *dispc,
1256 modes = dispc->feat->supported_color_modes[plane];
1266 const u32 *dispc_ovl_get_color_modes(struct dispc_device *dispc,
1269 return dispc->feat->supported_color_modes[plane];
1272 static void dispc_mgr_enable_cpr(struct dispc_device *dispc,
1278 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_CPR, enable);
1281 static void dispc_mgr_set_cpr_coef(struct dispc_device *dispc,
1297 dispc_write_reg(dispc, DISPC_CPR_COEF_R(channel), coef_r);
1298 dispc_write_reg(dispc, DISPC_CPR_COEF_G(channel), coef_g);
1299 dispc_write_reg(dispc, DISPC_CPR_COEF_B(channel), coef_b);
1302 static void dispc_ovl_set_vid_color_conv(struct dispc_device *dispc,
1309 val = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
1311 dispc_write_reg(dispc, DISPC_OVL_ATTRIBUTES(plane), val);
1314 static void dispc_ovl_enable_replication(struct dispc_device *dispc,
1326 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
1329 static void dispc_mgr_set_size(struct dispc_device *dispc,
1334 val = FLD_VAL(height - 1, dispc->feat->mgr_height_start, 16) |
1335 FLD_VAL(width - 1, dispc->feat->mgr_width_start, 0);
1337 dispc_write_reg(dispc, DISPC_SIZE_MGR(channel), val);
1340 static void dispc_init_fifos(struct dispc_device *dispc)
1348 unit = dispc->feat->buffer_size_unit;
1350 dispc_get_reg_field(dispc, FEAT_REG_FIFOSIZE, &start, &end);
1352 for (fifo = 0; fifo < dispc->feat->num_fifos; ++fifo) {
1353 size = REG_GET(dispc, DISPC_OVL_FIFO_SIZE_STATUS(fifo),
1356 dispc->fifo_size[fifo] = size;
1362 dispc->fifo_assignment[fifo] = fifo;
1372 if (dispc->feat->gfx_fifo_workaround) {
1375 v = dispc_read_reg(dispc, DISPC_GLOBAL_BUFFER);
1382 dispc_write_reg(dispc, DISPC_GLOBAL_BUFFER, v);
1384 dispc->fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
1385 dispc->fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
1391 for (i = 0; i < dispc_get_num_ovls(dispc); ++i) {
1396 dispc_ovl_compute_fifo_thresholds(dispc, i, &low, &high,
1399 dispc_ovl_set_fifo_threshold(dispc, i, low, high);
1402 if (dispc->feat->has_writeback) {
1407 dispc_ovl_compute_fifo_thresholds(dispc, OMAP_DSS_WB,
1411 dispc_ovl_set_fifo_threshold(dispc, OMAP_DSS_WB, low, high);
1415 static u32 dispc_ovl_get_fifo_size(struct dispc_device *dispc,
1421 for (fifo = 0; fifo < dispc->feat->num_fifos; ++fifo) {
1422 if (dispc->fifo_assignment[fifo] == plane)
1423 size += dispc->fifo_size[fifo];
1429 void dispc_ovl_set_fifo_threshold(struct dispc_device *dispc,
1436 unit = dispc->feat->buffer_size_unit;
1444 dispc_get_reg_field(dispc, FEAT_REG_FIFOHIGHTHRESHOLD,
1446 dispc_get_reg_field(dispc, FEAT_REG_FIFOLOWTHRESHOLD,
1451 REG_GET(dispc, DISPC_OVL_FIFO_THRESHOLD(plane),
1453 REG_GET(dispc, DISPC_OVL_FIFO_THRESHOLD(plane),
1457 dispc_write_reg(dispc, DISPC_OVL_FIFO_THRESHOLD(plane),
1466 if (dispc_has_feature(dispc, FEAT_PRELOAD) &&
1467 dispc->feat->set_max_preload && plane != OMAP_DSS_WB)
1468 dispc_write_reg(dispc, DISPC_OVL_PRELOAD(plane),
1472 void dispc_ovl_compute_fifo_thresholds(struct dispc_device *dispc,
1481 unsigned int buf_unit = dispc->feat->buffer_size_unit;
1485 burst_size = dispc_ovl_get_burst_size(dispc, plane);
1486 ovl_fifo_size = dispc_ovl_get_fifo_size(dispc, plane);
1490 for (i = 0; i < dispc_get_num_ovls(dispc); ++i)
1491 total_fifo_size += dispc_ovl_get_fifo_size(dispc, i);
1502 if (manual_update && dispc_has_feature(dispc, FEAT_OMAP3_DSI_FIFO_BUG)) {
1519 static void dispc_ovl_set_mflag(struct dispc_device *dispc,
1529 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
1532 static void dispc_ovl_set_mflag_threshold(struct dispc_device *dispc,
1536 dispc_write_reg(dispc, DISPC_OVL_MFLAG_THRESHOLD(plane),
1540 static void dispc_init_mflag(struct dispc_device *dispc)
1554 dispc_write_reg(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE,
1558 for (i = 0; i < dispc_get_num_ovls(dispc); ++i) {
1559 u32 size = dispc_ovl_get_fifo_size(dispc, i);
1560 u32 unit = dispc->feat->buffer_size_unit;
1563 dispc_ovl_set_mflag(dispc, i, true);
1574 dispc_ovl_set_mflag_threshold(dispc, i, low, high);
1577 if (dispc->feat->has_writeback) {
1578 u32 size = dispc_ovl_get_fifo_size(dispc, OMAP_DSS_WB);
1579 u32 unit = dispc->feat->buffer_size_unit;
1582 dispc_ovl_set_mflag(dispc, OMAP_DSS_WB, true);
1593 dispc_ovl_set_mflag_threshold(dispc, OMAP_DSS_WB, low, high);
1597 static void dispc_ovl_set_fir(struct dispc_device *dispc,
1607 dispc_get_reg_field(dispc, FEAT_REG_FIRHINC,
1609 dispc_get_reg_field(dispc, FEAT_REG_FIRVINC,
1614 dispc_write_reg(dispc, DISPC_OVL_FIR(plane), val);
1617 dispc_write_reg(dispc, DISPC_OVL_FIR2(plane), val);
1621 static void dispc_ovl_set_vid_accu0(struct dispc_device *dispc,
1628 dispc_get_reg_field(dispc, FEAT_REG_HORIZONTALACCU,
1630 dispc_get_reg_field(dispc, FEAT_REG_VERTICALACCU,
1636 dispc_write_reg(dispc, DISPC_OVL_ACCU0(plane), val);
1639 static void dispc_ovl_set_vid_accu1(struct dispc_device *dispc,
1646 dispc_get_reg_field(dispc, FEAT_REG_HORIZONTALACCU,
1648 dispc_get_reg_field(dispc, FEAT_REG_VERTICALACCU,
1654 dispc_write_reg(dispc, DISPC_OVL_ACCU1(plane), val);
1657 static void dispc_ovl_set_vid_accu2_0(struct dispc_device *dispc,
1664 dispc_write_reg(dispc, DISPC_OVL_ACCU2_0(plane), val);
1667 static void dispc_ovl_set_vid_accu2_1(struct dispc_device *dispc,
1674 dispc_write_reg(dispc, DISPC_OVL_ACCU2_1(plane), val);
1677 static void dispc_ovl_set_scale_param(struct dispc_device *dispc,
1689 dispc_ovl_set_scale_coef(dispc, plane, fir_hinc, fir_vinc, five_taps,
1691 dispc_ovl_set_fir(dispc, plane, fir_hinc, fir_vinc, color_comp);
1694 static void dispc_ovl_set_accu_uv(struct dispc_device *dispc,
1779 dispc_ovl_set_vid_accu2_0(dispc, plane, h_accu2_0, v_accu2_0);
1780 dispc_ovl_set_vid_accu2_1(dispc, plane, h_accu2_1, v_accu2_1);
1783 static void dispc_ovl_set_scaling_common(struct dispc_device *dispc,
1795 dispc_ovl_set_scale_param(dispc, plane, orig_width, orig_height,
1798 l = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane));
1807 if (dispc_has_feature(dispc, FEAT_RESIZECONF)) {
1814 if (dispc_has_feature(dispc, FEAT_LINEBUFFERSPLIT)) {
1819 dispc_write_reg(dispc, DISPC_OVL_ATTRIBUTES(plane), l);
1834 dispc_ovl_set_vid_accu0(dispc, plane, 0, accu0);
1835 dispc_ovl_set_vid_accu1(dispc, plane, 0, accu1);
1838 static void dispc_ovl_set_scaling_uv(struct dispc_device *dispc,
1853 if (!dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE))
1859 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane),
1864 dispc_ovl_set_accu_uv(dispc, plane, orig_width, orig_height, out_width,
1907 dispc_ovl_set_scale_param(dispc, plane, orig_width, orig_height,
1912 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane),
1916 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
1918 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
1921 static void dispc_ovl_set_scaling(struct dispc_device *dispc,
1931 dispc_ovl_set_scaling_common(dispc, plane, orig_width, orig_height,
1935 dispc_ovl_set_scaling_uv(dispc, plane, orig_width, orig_height,
1940 static void dispc_ovl_set_rotation_attrs(struct dispc_device *dispc,
1997 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12);
1998 if (dispc_has_feature(dispc, FEAT_ROWREPEATENABLE))
1999 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane),
2002 if (dispc_ovl_color_mode_supported(dispc, plane, DRM_FORMAT_NV12)) {
2009 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane),
2246 static int dispc_ovl_calc_scaling_24xx(struct dispc_device *dispc,
2260 const int maxsinglelinewidth = dispc->feat->max_line_width;
2267 *core_clk = dispc->feat->calc_core_clk(pclk, in_width,
2270 *core_clk > dispc_core_clk_rate(dispc));
2295 static int dispc_ovl_calc_scaling_34xx(struct dispc_device *dispc,
2308 const int maxsinglelinewidth = dispc->feat->max_line_width;
2325 *core_clk = dispc->feat->calc_core_clk(pclk, in_width,
2339 !*core_clk || *core_clk > dispc_core_clk_rate(dispc));
2383 static int dispc_ovl_calc_scaling_44xx(struct dispc_device *dispc,
2397 const int maxsinglelinewidth = dispc->feat->max_line_width;
2398 const int maxdownscale = dispc->feat->max_downscale;
2403 in_width_max = dispc_core_clk_rate(dispc)
2442 *core_clk = dispc->feat->calc_core_clk(pclk, in_width, in_height,
2447 enum omap_overlay_caps dispc_ovl_get_caps(struct dispc_device *dispc, enum omap_plane_id plane)
2449 return dispc->feat->overlay_caps[plane];
2455 static int dispc_ovl_calc_scaling(struct dispc_device *dispc,
2467 int maxhdownscale = dispc->feat->max_downscale;
2468 int maxvdownscale = dispc->feat->max_downscale;
2476 if (dispc->feat->supported_scaler_color_modes) {
2477 const u32 *modes = dispc->feat->supported_scaler_color_modes;
2516 dispc_has_feature(dispc, FEAT_BURST_2D)) ?
2529 ret = dispc->feat->calc_scaling(dispc, pclk, lclk, vm, width, height,
2549 core_clk, dispc_core_clk_rate(dispc));
2551 if (!core_clk || core_clk > dispc_core_clk_rate(dispc)) {
2555 core_clk, dispc_core_clk_rate(dispc));
2564 void dispc_ovl_get_max_size(struct dispc_device *dispc, u16 *width, u16 *height)
2566 *width = dispc->feat->ovl_width_max;
2567 *height = dispc->feat->ovl_height_max;
2570 static int dispc_ovl_setup_common(struct dispc_device *dispc,
2597 unsigned long pclk = dispc_plane_pclk_rate(dispc, plane);
2598 unsigned long lclk = dispc_plane_lclk_rate(dispc, plane);
2633 if (!dispc_ovl_color_mode_supported(dispc, plane, fourcc))
2636 r = dispc_ovl_calc_scaling(dispc, plane, pclk, lclk, caps, vm, in_width,
2698 dispc_ovl_set_color_mode(dispc, plane, fourcc);
2700 dispc_ovl_configure_burst_type(dispc, plane, rotation_type);
2702 if (dispc->feat->reverse_ilace_field_order)
2705 dispc_ovl_set_ba0(dispc, plane, paddr + offset0);
2706 dispc_ovl_set_ba1(dispc, plane, paddr + offset1);
2709 dispc_ovl_set_ba0_uv(dispc, plane, p_uv_addr + offset0);
2710 dispc_ovl_set_ba1_uv(dispc, plane, p_uv_addr + offset1);
2713 if (dispc->feat->last_pixel_inc_missing)
2716 dispc_ovl_set_row_inc(dispc, plane, row_inc);
2717 dispc_ovl_set_pix_inc(dispc, plane, pix_inc);
2722 dispc_ovl_set_pos(dispc, plane, caps, pos_x, pos_y);
2724 dispc_ovl_set_input_size(dispc, plane, in_width, in_height);
2727 dispc_ovl_set_scaling(dispc, plane, in_width, in_height,
2730 dispc_ovl_set_output_size(dispc, plane, out_width, out_height);
2731 dispc_ovl_set_vid_color_conv(dispc, plane, cconv);
2734 dispc_ovl_set_csc(dispc, plane, color_encoding, color_range);
2737 dispc_ovl_set_rotation_attrs(dispc, plane, rotation, rotation_type,
2740 dispc_ovl_set_zorder(dispc, plane, caps, zorder);
2741 dispc_ovl_set_pre_mult_alpha(dispc, plane, caps, pre_mult_alpha);
2742 dispc_ovl_setup_global_alpha(dispc, plane, caps, global_alpha);
2744 dispc_ovl_enable_replication(dispc, plane, caps, replication);
2749 int dispc_ovl_setup(struct dispc_device *dispc,
2756 enum omap_overlay_caps caps = dispc->feat->overlay_caps[plane];
2765 dispc_ovl_set_channel_out(dispc, plane, channel);
2767 r = dispc_ovl_setup_common(dispc, plane, caps, oi->paddr, oi->p_uv_addr,
2777 int dispc_ovl_enable(struct dispc_device *dispc,
2782 REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
2787 static void dispc_lcd_enable_signal_polarity(struct dispc_device *dispc,
2790 if (!dispc_has_feature(dispc, FEAT_LCDENABLEPOL))
2793 REG_FLD_MOD(dispc, DISPC_CONTROL, act_high ? 1 : 0, 29, 29);
2796 void dispc_lcd_enable_signal(struct dispc_device *dispc, bool enable)
2798 if (!dispc_has_feature(dispc, FEAT_LCDENABLESIGNAL))
2801 REG_FLD_MOD(dispc, DISPC_CONTROL, enable ? 1 : 0, 28, 28);
2804 void dispc_pck_free_enable(struct dispc_device *dispc, bool enable)
2806 if (!dispc_has_feature(dispc, FEAT_PCKFREEENABLE))
2809 REG_FLD_MOD(dispc, DISPC_CONTROL, enable ? 1 : 0, 27, 27);
2812 static void dispc_mgr_enable_fifohandcheck(struct dispc_device *dispc,
2816 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable);
2820 static void dispc_mgr_set_lcd_type_tft(struct dispc_device *dispc,
2823 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_STNTFT, 1);
2826 static void dispc_set_loadmode(struct dispc_device *dispc,
2829 REG_FLD_MOD(dispc, DISPC_CONFIG, mode, 2, 1);
2833 static void dispc_mgr_set_default_color(struct dispc_device *dispc,
2836 dispc_write_reg(dispc, DISPC_DEFAULT_COLOR(channel), color);
2839 static void dispc_mgr_set_trans_key(struct dispc_device *dispc,
2844 mgr_fld_write(dispc, ch, DISPC_MGR_FLD_TCKSELECTION, type);
2846 dispc_write_reg(dispc, DISPC_TRANS_COLOR(ch), trans_key);
2849 static void dispc_mgr_enable_trans_key(struct dispc_device *dispc,
2852 mgr_fld_write(dispc, ch, DISPC_MGR_FLD_TCKENABLE, enable);
2855 static void dispc_mgr_enable_alpha_fixed_zorder(struct dispc_device *dispc,
2859 if (!dispc_has_feature(dispc, FEAT_ALPHA_FIXED_ZORDER))
2863 REG_FLD_MOD(dispc, DISPC_CONFIG, enable, 18, 18);
2865 REG_FLD_MOD(dispc, DISPC_CONFIG, enable, 19, 19);
2868 void dispc_mgr_setup(struct dispc_device *dispc,
2872 dispc_mgr_set_default_color(dispc, channel, info->default_color);
2873 dispc_mgr_set_trans_key(dispc, channel, info->trans_key_type,
2875 dispc_mgr_enable_trans_key(dispc, channel, info->trans_enabled);
2876 dispc_mgr_enable_alpha_fixed_zorder(dispc, channel,
2878 if (dispc_has_feature(dispc, FEAT_CPR)) {
2879 dispc_mgr_enable_cpr(dispc, channel, info->cpr_enable);
2880 dispc_mgr_set_cpr_coef(dispc, channel, &info->cpr_coefs);
2884 static void dispc_mgr_set_tft_data_lines(struct dispc_device *dispc,
2908 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_TFTDATALINES, code);
2911 static void dispc_mgr_set_io_pad_mode(struct dispc_device *dispc,
2935 l = dispc_read_reg(dispc, DISPC_CONTROL);
2938 dispc_write_reg(dispc, DISPC_CONTROL, l);
2941 static void dispc_mgr_enable_stallmode(struct dispc_device *dispc,
2944 mgr_fld_write(dispc, channel, DISPC_MGR_FLD_STALLMODE, enable);
2947 void dispc_mgr_set_lcd_config(struct dispc_device *dispc,
2951 dispc_mgr_set_io_pad_mode(dispc, config->io_pad_mode);
2953 dispc_mgr_enable_stallmode(dispc, channel, config->stallmode);
2954 dispc_mgr_enable_fifohandcheck(dispc, channel, config->fifohandcheck);
2956 dispc_mgr_set_clock_div(dispc, channel, &config->clock_info);
2958 dispc_mgr_set_tft_data_lines(dispc, channel, config->video_port_width);
2960 dispc_lcd_enable_signal_polarity(dispc, config->lcden_sig_polarity);
2962 dispc_mgr_set_lcd_type_tft(dispc, channel);
2965 static bool _dispc_mgr_size_ok(struct dispc_device *dispc,
2968 return width <= dispc->feat->mgr_width_max &&
2969 height <= dispc->feat->mgr_height_max;
2972 static bool _dispc_lcd_timings_ok(struct dispc_device *dispc,
2976 if (hsync_len < 1 || hsync_len > dispc->feat->sw_max ||
2977 hfp < 1 || hfp > dispc->feat->hp_max ||
2978 hbp < 1 || hbp > dispc->feat->hp_max ||
2979 vsw < 1 || vsw > dispc->feat->sw_max ||
2980 vfp < 0 || vfp > dispc->feat->vp_max ||
2981 vbp < 0 || vbp > dispc->feat->vp_max)
2986 static bool _dispc_mgr_pclk_ok(struct dispc_device *dispc,
2991 return pclk <= dispc->feat->max_lcd_pclk;
2993 return pclk <= dispc->feat->max_tv_pclk;
2996 int dispc_mgr_check_timings(struct dispc_device *dispc,
3000 if (!_dispc_mgr_size_ok(dispc, vm->hactive, vm->vactive))
3003 if (!_dispc_mgr_pclk_ok(dispc, channel, vm->pixelclock))
3011 if (!_dispc_lcd_timings_ok(dispc, vm->hsync_len,
3021 static void _dispc_mgr_set_lcd_timings(struct dispc_device *dispc,
3028 timing_h = FLD_VAL(vm->hsync_len - 1, dispc->feat->sw_start, 0) |
3029 FLD_VAL(vm->hfront_porch - 1, dispc->feat->fp_start, 8) |
3030 FLD_VAL(vm->hback_porch - 1, dispc->feat->bp_start, 20);
3031 timing_v = FLD_VAL(vm->vsync_len - 1, dispc->feat->sw_start, 0) |
3032 FLD_VAL(vm->vfront_porch, dispc->feat->fp_start, 8) |
3033 FLD_VAL(vm->vback_porch, dispc->feat->bp_start, 20);
3035 dispc_write_reg(dispc, DISPC_TIMING_H(channel), timing_h);
3036 dispc_write_reg(dispc, DISPC_TIMING_V(channel), timing_v);
3053 if (dispc->feat->supports_sync_align)
3056 dispc_write_reg(dispc, DISPC_POL_FREQ(channel), l);
3058 if (dispc->syscon_pol) {
3073 regmap_update_bits(dispc->syscon_pol, dispc->syscon_pol_offset,
3089 void dispc_mgr_set_timings(struct dispc_device *dispc,
3099 if (dispc_mgr_check_timings(dispc, channel, &t)) {
3105 _dispc_mgr_set_lcd_timings(dispc, channel, &t);
3129 if (dispc->feat->supports_double_pixel)
3130 REG_FLD_MOD(dispc, DISPC_CONTROL,
3135 dispc_mgr_set_size(dispc, channel, t.hactive, t.vactive);
3138 static void dispc_mgr_set_lcd_divisor(struct dispc_device *dispc,
3145 dispc_write_reg(dispc, DISPC_DIVISORo(channel),
3148 if (!dispc_has_feature(dispc, FEAT_CORE_CLK_DIV) &&
3150 dispc->core_clk_rate = dispc_fclk_rate(dispc) / lck_div;
3153 static void dispc_mgr_get_lcd_divisor(struct dispc_device *dispc,
3158 l = dispc_read_reg(dispc, DISPC_DIVISORo(channel));
3163 static unsigned long dispc_fclk_rate(struct dispc_device *dispc)
3168 src = dss_get_dispc_clk_source(dispc->dss);
3171 r = dss_get_dispc_clk_rate(dispc->dss);
3176 pll = dss_pll_find_by_src(dispc->dss, src);
3185 static unsigned long dispc_mgr_lclk_rate(struct dispc_device *dispc,
3194 return dispc_fclk_rate(dispc);
3196 src = dss_get_lcd_clk_source(dispc->dss, channel);
3199 r = dss_get_dispc_clk_rate(dispc->dss);
3204 pll = dss_pll_find_by_src(dispc->dss, src);
3210 lcd = REG_GET(dispc, DISPC_DIVISORo(channel), 23, 16);
3215 static unsigned long dispc_mgr_pclk_rate(struct dispc_device *dispc,
3224 l = dispc_read_reg(dispc, DISPC_DIVISORo(channel));
3228 r = dispc_mgr_lclk_rate(dispc, channel);
3232 return dispc->tv_pclk_rate;
3236 void dispc_set_tv_pclk(struct dispc_device *dispc, unsigned long pclk)
3238 dispc->tv_pclk_rate = pclk;
3241 static unsigned long dispc_core_clk_rate(struct dispc_device *dispc)
3243 return dispc->core_clk_rate;
3246 static unsigned long dispc_plane_pclk_rate(struct dispc_device *dispc,
3254 channel = dispc_ovl_get_channel_out(dispc, plane);
3256 return dispc_mgr_pclk_rate(dispc, channel);
3259 static unsigned long dispc_plane_lclk_rate(struct dispc_device *dispc,
3267 channel = dispc_ovl_get_channel_out(dispc, plane);
3269 return dispc_mgr_lclk_rate(dispc, channel);
3272 static void dispc_dump_clocks_channel(struct dispc_device *dispc,
3281 lcd_clk_src = dss_get_lcd_clk_source(dispc->dss, channel);
3286 dispc_mgr_get_lcd_divisor(dispc, channel, &lcd, &pcd);
3289 dispc_mgr_lclk_rate(dispc, channel), lcd);
3291 dispc_mgr_pclk_rate(dispc, channel), pcd);
3294 void dispc_dump_clocks(struct dispc_device *dispc, struct seq_file *s)
3300 if (dispc_runtime_get(dispc))
3305 dispc_clk_src = dss_get_dispc_clk_source(dispc->dss);
3306 seq_printf(s, "dispc fclk source = %s\n",
3309 seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate(dispc));
3311 if (dispc_has_feature(dispc, FEAT_CORE_CLK_DIV)) {
3313 l = dispc_read_reg(dispc, DISPC_DIVISOR);
3317 (dispc_fclk_rate(dispc)/lcd), lcd);
3320 dispc_dump_clocks_channel(dispc, s, OMAP_DSS_CHANNEL_LCD);
3322 if (dispc_has_feature(dispc, FEAT_MGR_LCD2))
3323 dispc_dump_clocks_channel(dispc, s, OMAP_DSS_CHANNEL_LCD2);
3324 if (dispc_has_feature(dispc, FEAT_MGR_LCD3))
3325 dispc_dump_clocks_channel(dispc, s, OMAP_DSS_CHANNEL_LCD3);
3327 dispc_runtime_put(dispc);
3332 struct dispc_device *dispc = s->private;
3349 #define DUMPREG(dispc, r) \
3350 seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(dispc, r))
3352 if (dispc_runtime_get(dispc))
3356 DUMPREG(dispc, DISPC_REVISION);
3357 DUMPREG(dispc, DISPC_SYSCONFIG);
3358 DUMPREG(dispc, DISPC_SYSSTATUS);
3359 DUMPREG(dispc, DISPC_IRQSTATUS);
3360 DUMPREG(dispc, DISPC_IRQENABLE);
3361 DUMPREG(dispc, DISPC_CONTROL);
3362 DUMPREG(dispc, DISPC_CONFIG);
3363 DUMPREG(dispc, DISPC_CAPABLE);
3364 DUMPREG(dispc, DISPC_LINE_STATUS);
3365 DUMPREG(dispc, DISPC_LINE_NUMBER);
3366 if (dispc_has_feature(dispc, FEAT_ALPHA_FIXED_ZORDER) ||
3367 dispc_has_feature(dispc, FEAT_ALPHA_FREE_ZORDER))
3368 DUMPREG(dispc, DISPC_GLOBAL_ALPHA);
3369 if (dispc_has_feature(dispc, FEAT_MGR_LCD2)) {
3370 DUMPREG(dispc, DISPC_CONTROL2);
3371 DUMPREG(dispc, DISPC_CONFIG2);
3373 if (dispc_has_feature(dispc, FEAT_MGR_LCD3)) {
3374 DUMPREG(dispc, DISPC_CONTROL3);
3375 DUMPREG(dispc, DISPC_CONFIG3);
3377 if (dispc_has_feature(dispc, FEAT_MFLAG))
3378 DUMPREG(dispc, DISPC_GLOBAL_MFLAG_ATTRIBUTE);
3383 #define DUMPREG(dispc, i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \
3385 dispc_read_reg(dispc, DISPC_REG(i, r)))
3390 for (i = 0; i < dispc_get_num_mgrs(dispc); i++) {
3391 DUMPREG(dispc, i, DISPC_DEFAULT_COLOR);
3392 DUMPREG(dispc, i, DISPC_TRANS_COLOR);
3393 DUMPREG(dispc, i, DISPC_SIZE_MGR);
3398 DUMPREG(dispc, i, DISPC_TIMING_H);
3399 DUMPREG(dispc, i, DISPC_TIMING_V);
3400 DUMPREG(dispc, i, DISPC_POL_FREQ);
3401 DUMPREG(dispc, i, DISPC_DIVISORo);
3403 DUMPREG(dispc, i, DISPC_DATA_CYCLE1);
3404 DUMPREG(dispc, i, DISPC_DATA_CYCLE2);
3405 DUMPREG(dispc, i, DISPC_DATA_CYCLE3);
3407 if (dispc_has_feature(dispc, FEAT_CPR)) {
3408 DUMPREG(dispc, i, DISPC_CPR_COEF_R);
3409 DUMPREG(dispc, i, DISPC_CPR_COEF_G);
3410 DUMPREG(dispc, i, DISPC_CPR_COEF_B);
3416 for (i = 0; i < dispc_get_num_ovls(dispc); i++) {
3417 DUMPREG(dispc, i, DISPC_OVL_BA0);
3418 DUMPREG(dispc, i, DISPC_OVL_BA1);
3419 DUMPREG(dispc, i, DISPC_OVL_POSITION);
3420 DUMPREG(dispc, i, DISPC_OVL_SIZE);
3421 DUMPREG(dispc, i, DISPC_OVL_ATTRIBUTES);
3422 DUMPREG(dispc, i, DISPC_OVL_FIFO_THRESHOLD);
3423 DUMPREG(dispc, i, DISPC_OVL_FIFO_SIZE_STATUS);
3424 DUMPREG(dispc, i, DISPC_OVL_ROW_INC);
3425 DUMPREG(dispc, i, DISPC_OVL_PIXEL_INC);
3427 if (dispc_has_feature(dispc, FEAT_PRELOAD))
3428 DUMPREG(dispc, i, DISPC_OVL_PRELOAD);
3429 if (dispc_has_feature(dispc, FEAT_MFLAG))
3430 DUMPREG(dispc, i, DISPC_OVL_MFLAG_THRESHOLD);
3433 DUMPREG(dispc, i, DISPC_OVL_WINDOW_SKIP);
3434 DUMPREG(dispc, i, DISPC_OVL_TABLE_BA);
3438 DUMPREG(dispc, i, DISPC_OVL_FIR);
3439 DUMPREG(dispc, i, DISPC_OVL_PICTURE_SIZE);
3440 DUMPREG(dispc, i, DISPC_OVL_ACCU0);
3441 DUMPREG(dispc, i, DISPC_OVL_ACCU1);
3442 if (dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE)) {
3443 DUMPREG(dispc, i, DISPC_OVL_BA0_UV);
3444 DUMPREG(dispc, i, DISPC_OVL_BA1_UV);
3445 DUMPREG(dispc, i, DISPC_OVL_FIR2);
3446 DUMPREG(dispc, i, DISPC_OVL_ACCU2_0);
3447 DUMPREG(dispc, i, DISPC_OVL_ACCU2_1);
3449 if (dispc_has_feature(dispc, FEAT_ATTR2))
3450 DUMPREG(dispc, i, DISPC_OVL_ATTRIBUTES2);
3453 if (dispc->feat->has_writeback) {
3455 DUMPREG(dispc, i, DISPC_OVL_BA0);
3456 DUMPREG(dispc, i, DISPC_OVL_BA1);
3457 DUMPREG(dispc, i, DISPC_OVL_SIZE);
3458 DUMPREG(dispc, i, DISPC_OVL_ATTRIBUTES);
3459 DUMPREG(dispc, i, DISPC_OVL_FIFO_THRESHOLD);
3460 DUMPREG(dispc, i, DISPC_OVL_FIFO_SIZE_STATUS);
3461 DUMPREG(dispc, i, DISPC_OVL_ROW_INC);
3462 DUMPREG(dispc, i, DISPC_OVL_PIXEL_INC);
3464 if (dispc_has_feature(dispc, FEAT_MFLAG))
3465 DUMPREG(dispc, i, DISPC_OVL_MFLAG_THRESHOLD);
3467 DUMPREG(dispc, i, DISPC_OVL_FIR);
3468 DUMPREG(dispc, i, DISPC_OVL_PICTURE_SIZE);
3469 DUMPREG(dispc, i, DISPC_OVL_ACCU0);
3470 DUMPREG(dispc, i, DISPC_OVL_ACCU1);
3471 if (dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE)) {
3472 DUMPREG(dispc, i, DISPC_OVL_BA0_UV);
3473 DUMPREG(dispc, i, DISPC_OVL_BA1_UV);
3474 DUMPREG(dispc, i, DISPC_OVL_FIR2);
3475 DUMPREG(dispc, i, DISPC_OVL_ACCU2_0);
3476 DUMPREG(dispc, i, DISPC_OVL_ACCU2_1);
3478 if (dispc_has_feature(dispc, FEAT_ATTR2))
3479 DUMPREG(dispc, i, DISPC_OVL_ATTRIBUTES2);
3486 #define DUMPREG(dispc, plane, name, i) \
3489 dispc_read_reg(dispc, DISPC_REG(plane, name, i)))
3494 for (i = 1; i < dispc_get_num_ovls(dispc); i++) {
3496 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_H, j);
3499 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_HV, j);
3502 DUMPREG(dispc, i, DISPC_OVL_CONV_COEF, j);
3504 if (dispc_has_feature(dispc, FEAT_FIR_COEF_V)) {
3506 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_V, j);
3509 if (dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE)) {
3511 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_H2, j);
3514 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_HV2, j);
3517 DUMPREG(dispc, i, DISPC_OVL_FIR_COEF_V2, j);
3521 dispc_runtime_put(dispc);
3530 int dispc_calc_clock_rates(struct dispc_device *dispc,
3545 bool dispc_div_calc(struct dispc_device *dispc, unsigned long dispc_freq,
3563 pckd_hw_min = dispc->feat->min_pcd;
3566 lck_max = dss_get_max_fck_rate(dispc->dss);
3589 if (dispc_has_feature(dispc, FEAT_CORE_CLK_DIV))
3590 fck = dispc_core_clk_rate(dispc);
3605 void dispc_mgr_set_clock_div(struct dispc_device *dispc,
3612 dispc_mgr_set_lcd_divisor(dispc, channel, cinfo->lck_div,
3616 u32 dispc_read_irqstatus(struct dispc_device *dispc)
3618 return dispc_read_reg(dispc, DISPC_IRQSTATUS);
3621 void dispc_clear_irqstatus(struct dispc_device *dispc, u32 mask)
3623 dispc_write_reg(dispc, DISPC_IRQSTATUS, mask);
3626 void dispc_write_irqenable(struct dispc_device *dispc, u32 mask)
3628 u32 old_mask = dispc_read_reg(dispc, DISPC_IRQENABLE);
3631 dispc_clear_irqstatus(dispc, (mask ^ old_mask) & mask);
3633 dispc_write_reg(dispc, DISPC_IRQENABLE, mask);
3636 dispc_read_reg(dispc, DISPC_IRQENABLE);
3639 void dispc_enable_sidle(struct dispc_device *dispc)
3642 REG_FLD_MOD(dispc, DISPC_SYSCONFIG, 2, 4, 3);
3645 void dispc_disable_sidle(struct dispc_device *dispc)
3647 REG_FLD_MOD(dispc, DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
3650 u32 dispc_mgr_gamma_size(struct dispc_device *dispc,
3655 if (!dispc->feat->has_gamma_table)
3661 static void dispc_mgr_write_gamma_table(struct dispc_device *dispc,
3665 u32 *table = dispc->gamma_table[channel];
3678 dispc_write_reg(dispc, gdesc->reg, v);
3682 static void dispc_restore_gamma_tables(struct dispc_device *dispc)
3686 if (!dispc->feat->has_gamma_table)
3689 dispc_mgr_write_gamma_table(dispc, OMAP_DSS_CHANNEL_LCD);
3691 dispc_mgr_write_gamma_table(dispc, OMAP_DSS_CHANNEL_DIGIT);
3693 if (dispc_has_feature(dispc, FEAT_MGR_LCD2))
3694 dispc_mgr_write_gamma_table(dispc, OMAP_DSS_CHANNEL_LCD2);
3696 if (dispc_has_feature(dispc, FEAT_MGR_LCD3))
3697 dispc_mgr_write_gamma_table(dispc, OMAP_DSS_CHANNEL_LCD3);
3705 void dispc_mgr_set_gamma(struct dispc_device *dispc,
3711 u32 *table = dispc->gamma_table[channel];
3717 if (!dispc->feat->has_gamma_table)
3749 if (dispc->is_enabled)
3750 dispc_mgr_write_gamma_table(dispc, channel);
3753 static int dispc_init_gamma_tables(struct dispc_device *dispc)
3757 if (!dispc->feat->has_gamma_table)
3760 for (channel = 0; channel < ARRAY_SIZE(dispc->gamma_table); channel++) {
3765 !dispc_has_feature(dispc, FEAT_MGR_LCD2))
3769 !dispc_has_feature(dispc, FEAT_MGR_LCD3))
3772 gt = devm_kmalloc_array(&dispc->pdev->dev, gdesc->len,
3777 dispc->gamma_table[channel] = gt;
3779 dispc_mgr_set_gamma(dispc, channel, NULL, 0);
3784 static void _omap_dispc_initial_config(struct dispc_device *dispc)
3789 if (dispc_has_feature(dispc, FEAT_CORE_CLK_DIV)) {
3790 l = dispc_read_reg(dispc, DISPC_DIVISOR);
3794 dispc_write_reg(dispc, DISPC_DIVISOR, l);
3796 dispc->core_clk_rate = dispc_fclk_rate(dispc);
3800 if (dispc->feat->has_gamma_table)
3801 REG_FLD_MOD(dispc, DISPC_CONFIG, 1, 3, 3);
3805 * (dispc->feat->has_gamma_table) this enables tv-out gamma tables.
3807 if (dispc_has_feature(dispc, FEAT_FUNCGATED) ||
3808 dispc->feat->has_gamma_table)
3809 REG_FLD_MOD(dispc, DISPC_CONFIG, 1, 9, 9);
3811 dispc_set_loadmode(dispc, OMAP_DSS_LOAD_FRAME_ONLY);
3813 dispc_init_fifos(dispc);
3815 dispc_configure_burst_sizes(dispc);
3817 dispc_ovl_enable_zorder_planes(dispc);
3819 if (dispc->feat->mstandby_workaround)
3820 REG_FLD_MOD(dispc, DISPC_MSTANDBY_CTRL, 1, 0, 0);
3822 if (dispc_has_feature(dispc, FEAT_MFLAG))
3823 dispc_init_mflag(dispc);
4367 struct dispc_device *dispc = arg;
4369 if (!dispc->is_enabled)
4372 return dispc->user_handler(irq, dispc->user_data);
4375 int dispc_request_irq(struct dispc_device *dispc, irq_handler_t handler,
4380 if (dispc->user_handler != NULL)
4383 dispc->user_handler = handler;
4384 dispc->user_data = dev_id;
4389 r = devm_request_irq(&dispc->pdev->dev, dispc->irq, dispc_irq_handler,
4390 IRQF_SHARED, "OMAP DISPC", dispc);
4392 dispc->user_handler = NULL;
4393 dispc->user_data = NULL;
4399 void dispc_free_irq(struct dispc_device *dispc, void *dev_id)
4401 devm_free_irq(&dispc->pdev->dev, dispc->irq, dispc);
4403 dispc->user_handler = NULL;
4404 dispc->user_data = NULL;
4407 u32 dispc_get_memory_bandwidth_limit(struct dispc_device *dispc)
4412 of_property_read_u32(dispc->pdev->dev.of_node, "max-memory-bandwidth",
4419 * Workaround for errata i734 in DSS dispc
4489 static int dispc_errata_i734_wa_init(struct dispc_device *dispc)
4491 if (!dispc->feat->has_gamma_i734_bug)
4497 i734_buf.vaddr = dma_alloc_wc(&dispc->pdev->dev, i734_buf.size,
4500 dev_err(&dispc->pdev->dev, "%s: dma_alloc_wc failed\n",
4508 static void dispc_errata_i734_wa_fini(struct dispc_device *dispc)
4510 if (!dispc->feat->has_gamma_i734_bug)
4513 dma_free_wc(&dispc->pdev->dev, i734_buf.size, i734_buf.vaddr,
4517 static void dispc_errata_i734_wa(struct dispc_device *dispc)
4519 u32 framedone_irq = dispc_mgr_get_framedone_irq(dispc,
4526 if (!dispc->feat->has_gamma_i734_bug)
4529 gatestate = REG_GET(dispc, DISPC_CONFIG, 8, 4);
4536 REG_FLD_MOD(dispc, DISPC_CONFIG, 0x1f, 8, 4);
4539 dispc_ovl_setup(dispc, OMAP_DSS_GFX, &ovli, &i734.vm, false,
4541 dispc_ovl_enable(dispc, OMAP_DSS_GFX, true);
4544 dispc_mgr_setup(dispc, OMAP_DSS_CHANNEL_LCD, &i734.mgri);
4545 dispc_calc_clock_rates(dispc, dss_get_dispc_clk_rate(dispc->dss),
4547 dispc_mgr_set_lcd_config(dispc, OMAP_DSS_CHANNEL_LCD, &lcd_conf);
4548 dispc_mgr_set_timings(dispc, OMAP_DSS_CHANNEL_LCD, &i734.vm);
4550 dispc_clear_irqstatus(dispc, framedone_irq);
4553 dispc_mgr_enable(dispc, OMAP_DSS_CHANNEL_LCD, true);
4554 dispc_mgr_enable(dispc, OMAP_DSS_CHANNEL_LCD, false);
4561 while (!(dispc_read_irqstatus(dispc) & framedone_irq)) {
4563 dev_err(&dispc->pdev->dev, "%s: framedone timeout\n",
4568 dispc_ovl_enable(dispc, OMAP_DSS_GFX, false);
4571 dispc_clear_irqstatus(dispc, 0xffffffff);
4574 REG_FLD_MOD(dispc, DISPC_CONFIG, gatestate, 8, 4);
4579 { .compatible = "ti,omap2-dispc", .data = &omap24xx_dispc_feats },
4580 { .compatible = "ti,omap3-dispc", .data = &omap36xx_dispc_feats },
4581 { .compatible = "ti,omap4-dispc", .data = &omap44xx_dispc_feats },
4582 { .compatible = "ti,omap5-dispc", .data = &omap54xx_dispc_feats },
4583 { .compatible = "ti,dra7-dispc", .data = &omap54xx_dispc_feats },
4601 struct dispc_device *dispc;
4606 dispc = kzalloc(sizeof(*dispc), GFP_KERNEL);
4607 if (!dispc)
4610 dispc->pdev = pdev;
4611 platform_set_drvdata(pdev, dispc);
4612 dispc->dss = dss;
4620 dispc->feat = soc->data;
4622 dispc->feat = device_get_match_data(&pdev->dev);
4624 r = dispc_errata_i734_wa_init(dispc);
4628 dispc->base = devm_platform_ioremap_resource(pdev, 0);
4629 if (IS_ERR(dispc->base)) {
4630 r = PTR_ERR(dispc->base);
4634 dispc->irq = platform_get_irq(dispc->pdev, 0);
4635 if (dispc->irq < 0) {
4642 dispc->syscon_pol = syscon_regmap_lookup_by_phandle(np, "syscon-pol");
4643 if (IS_ERR(dispc->syscon_pol)) {
4645 r = PTR_ERR(dispc->syscon_pol);
4650 &dispc->syscon_pol_offset)) {
4657 r = dispc_init_gamma_tables(dispc);
4663 r = dispc_runtime_get(dispc);
4667 _omap_dispc_initial_config(dispc);
4669 rev = dispc_read_reg(dispc, DISPC_REVISION);
4673 dispc_runtime_put(dispc);
4675 dss->dispc = dispc;
4677 dispc->debugfs = dss_debugfs_create_file(dss, "dispc", dispc_dump_regs,
4678 dispc);
4685 kfree(dispc);
4691 struct dispc_device *dispc = dev_get_drvdata(dev);
4692 struct dss_device *dss = dispc->dss;
4694 dss_debugfs_remove_file(dispc->debugfs);
4696 dss->dispc = NULL;
4700 dispc_errata_i734_wa_fini(dispc);
4702 kfree(dispc);
4722 struct dispc_device *dispc = dev_get_drvdata(dev);
4724 dispc->is_enabled = false;
4728 synchronize_irq(dispc->irq);
4730 dispc_save_context(dispc);
4737 struct dispc_device *dispc = dev_get_drvdata(dev);
4745 if (REG_GET(dispc, DISPC_CONFIG, 2, 1) != OMAP_DSS_LOAD_FRAME_ONLY) {
4746 _omap_dispc_initial_config(dispc);
4748 dispc_errata_i734_wa(dispc);
4750 dispc_restore_context(dispc);
4752 dispc_restore_gamma_tables(dispc);
4755 dispc->is_enabled = true;