diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm/dss/dispc.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/dss/dispc.c | 1525 |
1 files changed, 833 insertions, 692 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 5ac0145fbae6..0f4fdb221498 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -39,11 +39,14 @@ #include <linux/mfd/syscon.h> #include <linux/regmap.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/component.h> +#include <linux/sys_soc.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_blend.h> #include "omapdss.h" #include "dss.h" -#include "dss_features.h" #include "dispc.h" /* DISPC */ @@ -61,6 +64,33 @@ enum omap_burst_size { #define REG_FLD_MOD(idx, val, start, end) \ dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) +/* DISPC has feature id */ +enum dispc_feature_id { + FEAT_LCDENABLEPOL, + FEAT_LCDENABLESIGNAL, + FEAT_PCKFREEENABLE, + FEAT_FUNCGATED, + FEAT_MGR_LCD2, + FEAT_MGR_LCD3, + FEAT_LINEBUFFERSPLIT, + FEAT_ROWREPEATENABLE, + FEAT_RESIZECONF, + /* Independent core clk divider */ + FEAT_CORE_CLK_DIV, + FEAT_HANDLE_UV_SEPARATE, + FEAT_ATTR2, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FIXED_ZORDER, + FEAT_ALPHA_FREE_ZORDER, + FEAT_FIFO_MERGE, + /* An unknown HW bug causing the normal FIFO thresholds not to work */ + FEAT_OMAP3_DSI_FIFO_BUG, + FEAT_BURST_2D, + FEAT_MFLAG, +}; + struct dispc_features { u8 sw_start; u8 fp_start; @@ -74,16 +104,29 @@ struct dispc_features { u16 mgr_height_max; unsigned long max_lcd_pclk; unsigned long max_tv_pclk; + unsigned int max_downscale; + unsigned int max_line_width; + unsigned int min_pcd; int (*calc_scaling) (unsigned long pclk, unsigned long lclk, const struct videomode *vm, u16 width, u16 height, u16 out_width, u16 out_height, - enum omap_color_mode color_mode, bool *five_taps, + u32 fourcc, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, u16 pos_x, unsigned long *core_clk, bool mem_to_mem); unsigned long (*calc_core_clk) (unsigned long pclk, u16 width, u16 height, u16 out_width, u16 out_height, bool mem_to_mem); u8 num_fifos; + const enum dispc_feature_id *features; + unsigned int num_features; + const struct dss_reg_field *reg_fields; + const unsigned int num_reg_fields; + const enum omap_overlay_caps *overlay_caps; + const u32 **supported_color_modes; + unsigned int num_mgrs; + unsigned int num_ovls; + unsigned int buffer_size_unit; + unsigned int burst_size_unit; /* swap GFX & WB fifos */ bool gfx_fifo_workaround:1; @@ -158,7 +201,7 @@ enum omap_color_component { */ DISPC_COLOR_COMPONENT_RGB_Y = 1 << 0, /* used for UV component for - * OMAP_DSS_COLOR_YUV2, OMAP_DSS_COLOR_UYVY, OMAP_DSS_COLOR_NV12 + * DRM_FORMAT_YUYV, DRM_FORMAT_UYVY, DRM_FORMAT_NV12 * color formats on OMAP4 */ DISPC_COLOR_COMPONENT_UV = 1 << 1, @@ -178,6 +221,17 @@ enum mgr_reg_fields { DISPC_MGR_FLD_NUM, }; +/* DISPC register field id */ +enum dispc_feat_reg_field { + FEAT_REG_FIRHINC, + FEAT_REG_FIRVINC, + FEAT_REG_FIFOHIGHTHRESHOLD, + FEAT_REG_FIFOLOWTHRESHOLD, + FEAT_REG_FIFOSIZE, + FEAT_REG_HORIZONTALACCU, + FEAT_REG_VERTICALACCU, +}; + struct dispc_reg_field { u16 reg; u8 high; @@ -341,6 +395,38 @@ static void mgr_fld_write(enum omap_channel channel, spin_unlock_irqrestore(&dispc.control_lock, flags); } +static int dispc_get_num_ovls(void) +{ + return dispc.feat->num_ovls; +} + +static int dispc_get_num_mgrs(void) +{ + return dispc.feat->num_mgrs; +} + +static void dispc_get_reg_field(enum dispc_feat_reg_field id, + u8 *start, u8 *end) +{ + if (id >= dispc.feat->num_reg_fields) + BUG(); + + *start = dispc.feat->reg_fields[id].start; + *end = dispc.feat->reg_fields[id].end; +} + +static bool dispc_has_feature(enum dispc_feature_id id) +{ + unsigned int i; + + for (i = 0; i < dispc.feat->num_features; i++) { + if (dispc.feat->features[i] == id) + return true; + } + + return false; +} + #define SR(reg) \ dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) #define RR(reg) \ @@ -356,19 +442,19 @@ static void dispc_save_context(void) SR(CONTROL); SR(CONFIG); SR(LINE_NUMBER); - if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || - dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) + if (dispc_has_feature(FEAT_ALPHA_FIXED_ZORDER) || + dispc_has_feature(FEAT_ALPHA_FREE_ZORDER)) SR(GLOBAL_ALPHA); - if (dss_has_feature(FEAT_MGR_LCD2)) { + if (dispc_has_feature(FEAT_MGR_LCD2)) { SR(CONTROL2); SR(CONFIG2); } - if (dss_has_feature(FEAT_MGR_LCD3)) { + if (dispc_has_feature(FEAT_MGR_LCD3)) { SR(CONTROL3); SR(CONFIG3); } - for (i = 0; i < dss_feat_get_num_mgrs(); i++) { + for (i = 0; i < dispc_get_num_mgrs(); i++) { SR(DEFAULT_COLOR(i)); SR(TRANS_COLOR(i)); SR(SIZE_MGR(i)); @@ -383,14 +469,14 @@ static void dispc_save_context(void) SR(DATA_CYCLE2(i)); SR(DATA_CYCLE3(i)); - if (dss_has_feature(FEAT_CPR)) { + if (dispc_has_feature(FEAT_CPR)) { SR(CPR_COEF_R(i)); SR(CPR_COEF_G(i)); SR(CPR_COEF_B(i)); } } - for (i = 0; i < dss_feat_get_num_ovls(); i++) { + for (i = 0; i < dispc_get_num_ovls(); i++) { SR(OVL_BA0(i)); SR(OVL_BA1(i)); SR(OVL_POSITION(i)); @@ -399,7 +485,7 @@ static void dispc_save_context(void) SR(OVL_FIFO_THRESHOLD(i)); SR(OVL_ROW_INC(i)); SR(OVL_PIXEL_INC(i)); - if (dss_has_feature(FEAT_PRELOAD)) + if (dispc_has_feature(FEAT_PRELOAD)) SR(OVL_PRELOAD(i)); if (i == OMAP_DSS_GFX) { SR(OVL_WINDOW_SKIP(i)); @@ -420,12 +506,12 @@ static void dispc_save_context(void) for (j = 0; j < 5; j++) SR(OVL_CONV_COEF(i, j)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { + if (dispc_has_feature(FEAT_FIR_COEF_V)) { for (j = 0; j < 8; j++) SR(OVL_FIR_COEF_V(i, j)); } - if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { + if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) { SR(OVL_BA0_UV(i)); SR(OVL_BA1_UV(i)); SR(OVL_FIR2(i)); @@ -441,11 +527,11 @@ static void dispc_save_context(void) for (j = 0; j < 8; j++) SR(OVL_FIR_COEF_V2(i, j)); } - if (dss_has_feature(FEAT_ATTR2)) + if (dispc_has_feature(FEAT_ATTR2)) SR(OVL_ATTRIBUTES2(i)); } - if (dss_has_feature(FEAT_CORE_CLK_DIV)) + if (dispc_has_feature(FEAT_CORE_CLK_DIV)) SR(DIVISOR); dispc.ctx_valid = true; @@ -466,15 +552,15 @@ static void dispc_restore_context(void) /*RR(CONTROL);*/ RR(CONFIG); RR(LINE_NUMBER); - if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || - dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) + if (dispc_has_feature(FEAT_ALPHA_FIXED_ZORDER) || + dispc_has_feature(FEAT_ALPHA_FREE_ZORDER)) RR(GLOBAL_ALPHA); - if (dss_has_feature(FEAT_MGR_LCD2)) + if (dispc_has_feature(FEAT_MGR_LCD2)) RR(CONFIG2); - if (dss_has_feature(FEAT_MGR_LCD3)) + if (dispc_has_feature(FEAT_MGR_LCD3)) RR(CONFIG3); - for (i = 0; i < dss_feat_get_num_mgrs(); i++) { + for (i = 0; i < dispc_get_num_mgrs(); i++) { RR(DEFAULT_COLOR(i)); RR(TRANS_COLOR(i)); RR(SIZE_MGR(i)); @@ -489,14 +575,14 @@ static void dispc_restore_context(void) RR(DATA_CYCLE2(i)); RR(DATA_CYCLE3(i)); - if (dss_has_feature(FEAT_CPR)) { + if (dispc_has_feature(FEAT_CPR)) { RR(CPR_COEF_R(i)); RR(CPR_COEF_G(i)); RR(CPR_COEF_B(i)); } } - for (i = 0; i < dss_feat_get_num_ovls(); i++) { + for (i = 0; i < dispc_get_num_ovls(); i++) { RR(OVL_BA0(i)); RR(OVL_BA1(i)); RR(OVL_POSITION(i)); @@ -505,7 +591,7 @@ static void dispc_restore_context(void) RR(OVL_FIFO_THRESHOLD(i)); RR(OVL_ROW_INC(i)); RR(OVL_PIXEL_INC(i)); - if (dss_has_feature(FEAT_PRELOAD)) + if (dispc_has_feature(FEAT_PRELOAD)) RR(OVL_PRELOAD(i)); if (i == OMAP_DSS_GFX) { RR(OVL_WINDOW_SKIP(i)); @@ -526,12 +612,12 @@ static void dispc_restore_context(void) for (j = 0; j < 5; j++) RR(OVL_CONV_COEF(i, j)); - if (dss_has_feature(FEAT_FIR_COEF_V)) { + if (dispc_has_feature(FEAT_FIR_COEF_V)) { for (j = 0; j < 8; j++) RR(OVL_FIR_COEF_V(i, j)); } - if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { + if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) { RR(OVL_BA0_UV(i)); RR(OVL_BA1_UV(i)); RR(OVL_FIR2(i)); @@ -547,18 +633,18 @@ static void dispc_restore_context(void) for (j = 0; j < 8; j++) RR(OVL_FIR_COEF_V2(i, j)); } - if (dss_has_feature(FEAT_ATTR2)) + if (dispc_has_feature(FEAT_ATTR2)) RR(OVL_ATTRIBUTES2(i)); } - if (dss_has_feature(FEAT_CORE_CLK_DIV)) + if (dispc_has_feature(FEAT_CORE_CLK_DIV)) RR(DIVISOR); /* enable last, because LCD & DIGIT enable are here */ RR(CONTROL); - if (dss_has_feature(FEAT_MGR_LCD2)) + if (dispc_has_feature(FEAT_MGR_LCD2)) RR(CONTROL2); - if (dss_has_feature(FEAT_MGR_LCD3)) + if (dispc_has_feature(FEAT_MGR_LCD3)) RR(CONTROL3); /* clear spurious SYNC_LOST_DIGIT interrupts */ dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT); @@ -777,7 +863,7 @@ static void dispc_ovl_write_color_conv_coef(enum omap_plane_id plane, static void dispc_setup_color_conv_coef(void) { int i; - int num_ovl = dss_feat_get_num_ovls(); + int num_ovl = dispc_get_num_ovls(); const struct color_conv_coef ctbl_bt601_5_ovl = { /* YUV -> RGB */ 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, @@ -866,10 +952,10 @@ static void dispc_ovl_enable_zorder_planes(void) { int i; - if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) + if (!dispc_has_feature(FEAT_ALPHA_FREE_ZORDER)) return; - for (i = 0; i < dss_feat_get_num_ovls(); i++) + for (i = 0; i < dispc_get_num_ovls(); i++) REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); } @@ -905,78 +991,69 @@ static void dispc_ovl_set_row_inc(enum omap_plane_id plane, s32 inc) dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc); } -static void dispc_ovl_set_color_mode(enum omap_plane_id plane, - enum omap_color_mode color_mode) +static void dispc_ovl_set_color_mode(enum omap_plane_id plane, u32 fourcc) { u32 m = 0; if (plane != OMAP_DSS_GFX) { - switch (color_mode) { - case OMAP_DSS_COLOR_NV12: + switch (fourcc) { + case DRM_FORMAT_NV12: m = 0x0; break; - case OMAP_DSS_COLOR_RGBX16: + case DRM_FORMAT_XRGB4444: m = 0x1; break; - case OMAP_DSS_COLOR_RGBA16: + case DRM_FORMAT_RGBA4444: m = 0x2; break; - case OMAP_DSS_COLOR_RGB12U: + case DRM_FORMAT_RGBX4444: m = 0x4; break; - case OMAP_DSS_COLOR_ARGB16: + case DRM_FORMAT_ARGB4444: m = 0x5; break; - case OMAP_DSS_COLOR_RGB16: + case DRM_FORMAT_RGB565: m = 0x6; break; - case OMAP_DSS_COLOR_ARGB16_1555: + case DRM_FORMAT_ARGB1555: m = 0x7; break; - case OMAP_DSS_COLOR_RGB24U: + case DRM_FORMAT_XRGB8888: m = 0x8; break; - case OMAP_DSS_COLOR_RGB24P: + case DRM_FORMAT_RGB888: m = 0x9; break; - case OMAP_DSS_COLOR_YUV2: + case DRM_FORMAT_YUYV: m = 0xa; break; - case OMAP_DSS_COLOR_UYVY: + case DRM_FORMAT_UYVY: m = 0xb; break; - case OMAP_DSS_COLOR_ARGB32: + case DRM_FORMAT_ARGB8888: m = 0xc; break; - case OMAP_DSS_COLOR_RGBA32: + case DRM_FORMAT_RGBA8888: m = 0xd; break; - case OMAP_DSS_COLOR_RGBX32: + case DRM_FORMAT_RGBX8888: m = 0xe; break; - case OMAP_DSS_COLOR_XRGB16_1555: + case DRM_FORMAT_XRGB1555: m = 0xf; break; default: BUG(); return; } } else { - switch (color_mode) { - case OMAP_DSS_COLOR_CLUT1: - m = 0x0; break; - case OMAP_DSS_COLOR_CLUT2: - m = 0x1; break; - case OMAP_DSS_COLOR_CLUT4: - m = 0x2; break; - case OMAP_DSS_COLOR_CLUT8: - m = 0x3; break; - case OMAP_DSS_COLOR_RGB12U: + switch (fourcc) { + case DRM_FORMAT_RGBX4444: m = 0x4; break; - case OMAP_DSS_COLOR_ARGB16: + case DRM_FORMAT_ARGB4444: m = 0x5; break; - case OMAP_DSS_COLOR_RGB16: + case DRM_FORMAT_RGB565: m = 0x6; break; - case OMAP_DSS_COLOR_ARGB16_1555: + case DRM_FORMAT_ARGB1555: m = 0x7; break; - case OMAP_DSS_COLOR_RGB24U: + case DRM_FORMAT_XRGB8888: m = 0x8; break; - case OMAP_DSS_COLOR_RGB24P: + case DRM_FORMAT_RGB888: m = 0x9; break; - case OMAP_DSS_COLOR_RGBX16: + case DRM_FORMAT_XRGB4444: m = 0xa; break; - case OMAP_DSS_COLOR_RGBA16: + case DRM_FORMAT_RGBA4444: m = 0xb; break; - case OMAP_DSS_COLOR_ARGB32: + case DRM_FORMAT_ARGB8888: m = 0xc; break; - case OMAP_DSS_COLOR_RGBA32: + case DRM_FORMAT_RGBA8888: m = 0xd; break; - case OMAP_DSS_COLOR_RGBX32: + case DRM_FORMAT_RGBX8888: m = 0xe; break; - case OMAP_DSS_COLOR_XRGB16_1555: + case DRM_FORMAT_XRGB1555: m = 0xf; break; default: BUG(); return; @@ -986,10 +1063,22 @@ static void dispc_ovl_set_color_mode(enum omap_plane_id plane, REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); } +static bool format_is_yuv(u32 fourcc) +{ + switch (fourcc) { + case DRM_FORMAT_YUYV: + case DRM_FORMAT_UYVY: + case DRM_FORMAT_NV12: + return true; + default: + return false; + } +} + static void dispc_ovl_configure_burst_type(enum omap_plane_id plane, enum omap_dss_rotation_type rotation_type) { - if (dss_has_feature(FEAT_BURST_2D) == 0) + if (dispc_has_feature(FEAT_BURST_2D) == 0) return; if (rotation_type == OMAP_DSS_ROT_TILER) @@ -1020,7 +1109,7 @@ static void dispc_ovl_set_channel_out(enum omap_plane_id plane, } val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); - if (dss_has_feature(FEAT_MGR_LCD2)) { + if (dispc_has_feature(FEAT_MGR_LCD2)) { switch (channel) { case OMAP_DSS_CHANNEL_LCD: chan = 0; @@ -1035,7 +1124,7 @@ static void dispc_ovl_set_channel_out(enum omap_plane_id plane, chan2 = 1; break; case OMAP_DSS_CHANNEL_LCD3: - if (dss_has_feature(FEAT_MGR_LCD3)) { + if (dispc_has_feature(FEAT_MGR_LCD3)) { chan = 0; chan2 = 2; } else { @@ -1084,7 +1173,7 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane_id plane) if (FLD_GET(val, shift, shift) == 1) return OMAP_DSS_CHANNEL_DIGIT; - if (!dss_has_feature(FEAT_MGR_LCD2)) + if (!dispc_has_feature(FEAT_MGR_LCD2)) return OMAP_DSS_CHANNEL_LCD; switch (FLD_GET(val, 31, 30)) { @@ -1123,7 +1212,7 @@ static void dispc_configure_burst_sizes(void) const int burst_size = BURST_SIZE_X8; /* Configure burst size always to maximum size */ - for (i = 0; i < dss_feat_get_num_ovls(); ++i) + for (i = 0; i < dispc_get_num_ovls(); ++i) dispc_ovl_set_burst_size(i, burst_size); if (dispc.feat->has_writeback) dispc_ovl_set_burst_size(OMAP_DSS_WB, burst_size); @@ -1131,19 +1220,28 @@ static void dispc_configure_burst_sizes(void) static u32 dispc_ovl_get_burst_size(enum omap_plane_id plane) { - unsigned unit = dss_feat_get_burst_size_unit(); /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ - return unit * 8; + return dispc.feat->burst_size_unit * 8; } -static enum omap_color_mode dispc_ovl_get_color_modes(enum omap_plane_id plane) +static bool dispc_ovl_color_mode_supported(enum omap_plane_id plane, u32 fourcc) { - return dss_feat_get_supported_color_modes(plane); + const u32 *modes; + unsigned int i; + + modes = dispc.feat->supported_color_modes[plane]; + + for (i = 0; modes[i]; ++i) { + if (modes[i] == fourcc) + return true; + } + + return false; } -static int dispc_get_num_ovls(void) +static const u32 *dispc_ovl_get_color_modes(enum omap_plane_id plane) { - return dss_feat_get_num_ovls(); + return dispc.feat->supported_color_modes[plane]; } static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) @@ -1218,9 +1316,9 @@ static void dispc_init_fifos(void) u32 unit; int i; - unit = dss_feat_get_buffer_size_unit(); + unit = dispc.feat->buffer_size_unit; - dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); + dispc_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) { size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end); @@ -1260,7 +1358,7 @@ static void dispc_init_fifos(void) /* * Setup default fifo thresholds. */ - for (i = 0; i < dss_feat_get_num_ovls(); ++i) { + for (i = 0; i < dispc_get_num_ovls(); ++i) { u32 low, high; const bool use_fifomerge = false; const bool manual_update = false; @@ -1302,7 +1400,7 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low, u8 hi_start, hi_end, lo_start, lo_end; u32 unit; - unit = dss_feat_get_buffer_size_unit(); + unit = dispc.feat->buffer_size_unit; WARN_ON(low % unit != 0); WARN_ON(high % unit != 0); @@ -1310,8 +1408,8 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low, low /= unit; high /= unit; - dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); - dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); + dispc_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); + dispc_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); DSSDBG("fifo(%d) threshold (bytes), old %u/%u, new %u/%u\n", plane, @@ -1330,14 +1428,14 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low, * large for the preload field, set the threshold to the maximum value * that can be held by the preload register */ - if (dss_has_feature(FEAT_PRELOAD) && dispc.feat->set_max_preload && + if (dispc_has_feature(FEAT_PRELOAD) && dispc.feat->set_max_preload && plane != OMAP_DSS_WB) dispc_write_reg(DISPC_OVL_PRELOAD(plane), min(high, 0xfffu)); } void dispc_enable_fifomerge(bool enable) { - if (!dss_has_feature(FEAT_FIFO_MERGE)) { + if (!dispc_has_feature(FEAT_FIFO_MERGE)) { WARN_ON(enable); return; } @@ -1355,7 +1453,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane, * buffer_units, and the fifo thresholds must be buffer_unit aligned. */ - unsigned buf_unit = dss_feat_get_buffer_size_unit(); + unsigned buf_unit = dispc.feat->buffer_size_unit; unsigned ovl_fifo_size, total_fifo_size, burst_size; int i; @@ -1364,7 +1462,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane, if (use_fifomerge) { total_fifo_size = 0; - for (i = 0; i < dss_feat_get_num_ovls(); ++i) + for (i = 0; i < dispc_get_num_ovls(); ++i) total_fifo_size += dispc_ovl_get_fifo_size(i); } else { total_fifo_size = ovl_fifo_size; @@ -1376,7 +1474,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane, * combined fifo size */ - if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { + if (manual_update && dispc_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { *fifo_low = ovl_fifo_size - burst_size * 2; *fifo_high = total_fifo_size - burst_size; } else if (plane == OMAP_DSS_WB) { @@ -1430,9 +1528,9 @@ static void dispc_init_mflag(void) (1 << 0) | /* MFLAG_CTRL = force always on */ (0 << 2)); /* MFLAG_START = disable */ - for (i = 0; i < dss_feat_get_num_ovls(); ++i) { + for (i = 0; i < dispc_get_num_ovls(); ++i) { u32 size = dispc_ovl_get_fifo_size(i); - u32 unit = dss_feat_get_buffer_size_unit(); + u32 unit = dispc.feat->buffer_size_unit; u32 low, high; dispc_ovl_set_mflag(i, true); @@ -1451,7 +1549,7 @@ static void dispc_init_mflag(void) if (dispc.feat->has_writeback) { u32 size = dispc_ovl_get_fifo_size(OMAP_DSS_WB); - u32 unit = dss_feat_get_buffer_size_unit(); + u32 unit = dispc.feat->buffer_size_unit; u32 low, high; dispc_ovl_set_mflag(OMAP_DSS_WB, true); @@ -1478,10 +1576,8 @@ static void dispc_ovl_set_fir(enum omap_plane_id plane, if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { u8 hinc_start, hinc_end, vinc_start, vinc_end; - dss_feat_get_reg_field(FEAT_REG_FIRHINC, - &hinc_start, &hinc_end); - dss_feat_get_reg_field(FEAT_REG_FIRVINC, - &vinc_start, &vinc_end); + dispc_get_reg_field(FEAT_REG_FIRHINC, &hinc_start, &hinc_end); + dispc_get_reg_field(FEAT_REG_FIRVINC, &vinc_start, &vinc_end); val = FLD_VAL(vinc, vinc_start, vinc_end) | FLD_VAL(hinc, hinc_start, hinc_end); @@ -1498,8 +1594,8 @@ static void dispc_ovl_set_vid_accu0(enum omap_plane_id plane, int haccu, u32 val; u8 hor_start, hor_end, vert_start, vert_end; - dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); - dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); + dispc_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); + dispc_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); val = FLD_VAL(vaccu, vert_start, vert_end) | FLD_VAL(haccu, hor_start, hor_end); @@ -1513,8 +1609,8 @@ static void dispc_ovl_set_vid_accu1(enum omap_plane_id plane, int haccu, u32 val; u8 hor_start, hor_end, vert_start, vert_end; - dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); - dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); + dispc_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); + dispc_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); val = FLD_VAL(vaccu, vert_start, vert_end) | FLD_VAL(haccu, hor_start, hor_end); @@ -1558,7 +1654,7 @@ static void dispc_ovl_set_scale_param(enum omap_plane_id plane, static void dispc_ovl_set_accu_uv(enum omap_plane_id plane, u16 orig_width, u16 orig_height, u16 out_width, u16 out_height, - bool ilace, enum omap_color_mode color_mode, u8 rotation) + bool ilace, u32 fourcc, u8 rotation) { int h_accu2_0, h_accu2_1; int v_accu2_0, v_accu2_1; @@ -1596,33 +1692,32 @@ static void dispc_ovl_set_accu_uv(enum omap_plane_id plane, { 0, 1, 0, 1, -1, 1, 0, 1 }, }; - switch (rotation) { - case OMAP_DSS_ROT_0: + /* Note: DSS HW rotates clockwise, DRM_MODE_ROTATE_* counter-clockwise */ + switch (rotation & DRM_MODE_ROTATE_MASK) { + default: + case DRM_MODE_ROTATE_0: idx = 0; break; - case OMAP_DSS_ROT_90: - idx = 1; + case DRM_MODE_ROTATE_90: + idx = 3; break; - case OMAP_DSS_ROT_180: + case DRM_MODE_ROTATE_180: idx = 2; break; - case OMAP_DSS_ROT_270: - idx = 3; + case DRM_MODE_ROTATE_270: + idx = 1; break; - default: - BUG(); - return; } - switch (color_mode) { - case OMAP_DSS_COLOR_NV12: + switch (fourcc) { + case DRM_FORMAT_NV12: if (ilace) accu_table = accu_nv12_ilace; else accu_table = accu_nv12; break; - case OMAP_DSS_COLOR_YUV2: - case OMAP_DSS_COLOR_UYVY: + case DRM_FORMAT_YUYV: + case DRM_FORMAT_UYVY: accu_table = accu_yuv; break; default: @@ -1648,7 +1743,7 @@ static void dispc_ovl_set_scaling_common(enum omap_plane_id plane, u16 orig_width, u16 orig_height, u16 out_width, u16 out_height, bool ilace, bool five_taps, - bool fieldmode, enum omap_color_mode color_mode, + bool fieldmode, u32 fourcc, u8 rotation) { int accu0 = 0; @@ -1667,14 +1762,14 @@ static void dispc_ovl_set_scaling_common(enum omap_plane_id plane, l |= five_taps ? (1 << 21) : 0; /* VRESIZECONF and HRESIZECONF */ - if (dss_has_feature(FEAT_RESIZECONF)) { + if (dispc_has_feature(FEAT_RESIZECONF)) { l &= ~(0x3 << 7); l |= (orig_width <= out_width) ? 0 : (1 << 7); l |= (orig_height <= out_height) ? 0 : (1 << 8); } /* LINEBUFFERSPLIT */ - if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) { + if (dispc_has_feature(FEAT_LINEBUFFERSPLIT)) { l &= ~(0x1 << 22); l |= five_taps ? (1 << 22) : 0; } @@ -1702,18 +1797,17 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane_id plane, u16 orig_width, u16 orig_height, u16 out_width, u16 out_height, bool ilace, bool five_taps, - bool fieldmode, enum omap_color_mode color_mode, + bool fieldmode, u32 fourcc, u8 rotation) { int scale_x = out_width != orig_width; int scale_y = out_height != orig_height; bool chroma_upscale = plane != OMAP_DSS_WB; - if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) + if (!dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) return; - if ((color_mode != OMAP_DSS_COLOR_YUV2 && - color_mode != OMAP_DSS_COLOR_UYVY && - color_mode != OMAP_DSS_COLOR_NV12)) { + + if (!format_is_yuv(fourcc)) { /* reset chroma resampling for RGB formats */ if (plane != OMAP_DSS_WB) REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); @@ -1721,10 +1815,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane_id plane, } dispc_ovl_set_accu_uv(plane, orig_width, orig_height, out_width, - out_height, ilace, color_mode, rotation); + out_height, ilace, fourcc, rotation); - switch (color_mode) { - case OMAP_DSS_COLOR_NV12: + switch (fourcc) { + case DRM_FORMAT_NV12: if (chroma_upscale) { /* UV is subsampled by 2 horizontally and vertically */ orig_height >>= 1; @@ -1736,11 +1830,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane_id plane, } break; - case OMAP_DSS_COLOR_YUV2: - case OMAP_DSS_COLOR_UYVY: + case DRM_FORMAT_YUYV: + case DRM_FORMAT_UYVY: /* For YUV422 with 90/270 rotation, we don't upsample chroma */ - if (rotation == OMAP_DSS_ROT_0 || - rotation == OMAP_DSS_ROT_180) { + if (!drm_rotation_90_or_270(rotation)) { if (chroma_upscale) /* UV is subsampled by 2 horizontally */ orig_width >>= 1; @@ -1750,7 +1843,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane_id plane, } /* must use FIR for YUV422 if rotated */ - if (rotation != OMAP_DSS_ROT_0) + if ((rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0) scale_x = scale_y = true; break; @@ -1782,7 +1875,7 @@ static void dispc_ovl_set_scaling(enum omap_plane_id plane, u16 orig_width, u16 orig_height, u16 out_width, u16 out_height, bool ilace, bool five_taps, - bool fieldmode, enum omap_color_mode color_mode, + bool fieldmode, u32 fourcc, u8 rotation) { BUG_ON(plane == OMAP_DSS_GFX); @@ -1791,60 +1884,59 @@ static void dispc_ovl_set_scaling(enum omap_plane_id plane, orig_width, orig_height, out_width, out_height, ilace, five_taps, - fieldmode, color_mode, + fieldmode, fourcc, rotation); dispc_ovl_set_scaling_uv(plane, orig_width, orig_height, out_width, out_height, ilace, five_taps, - fieldmode, color_mode, + fieldmode, fourcc, rotation); } static void dispc_ovl_set_rotation_attrs(enum omap_plane_id plane, u8 rotation, - enum omap_dss_rotation_type rotation_type, - bool mirroring, enum omap_color_mode color_mode) + enum omap_dss_rotation_type rotation_type, u32 fourcc) { bool row_repeat = false; int vidrot = 0; - if (color_mode == OMAP_DSS_COLOR_YUV2 || - color_mode == OMAP_DSS_COLOR_UYVY) { + /* Note: DSS HW rotates clockwise, DRM_MODE_ROTATE_* counter-clockwise */ + if (fourcc == DRM_FORMAT_YUYV || fourcc == DRM_FORMAT_UYVY) { - if (mirroring) { - switch (rotation) { - case OMAP_DSS_ROT_0: + if (rotation & DRM_MODE_REFLECT_X) { + switch (rotation & DRM_MODE_ROTATE_MASK) { + case DRM_MODE_ROTATE_0: vidrot = 2; break; - case OMAP_DSS_ROT_90: + case DRM_MODE_ROTATE_90: vidrot = 1; break; - case OMAP_DSS_ROT_180: + case DRM_MODE_ROTATE_180: vidrot = 0; break; - case OMAP_DSS_ROT_270: + case DRM_MODE_ROTATE_270: vidrot = 3; break; } } else { - switch (rotation) { - case OMAP_DSS_ROT_0: + switch (rotation & DRM_MODE_ROTATE_MASK) { + case DRM_MODE_ROTATE_0: vidrot = 0; break; - case OMAP_DSS_ROT_90: - vidrot = 1; + case DRM_MODE_ROTATE_90: + vidrot = 3; break; - case OMAP_DSS_ROT_180: + case DRM_MODE_ROTATE_180: vidrot = 2; break; - case OMAP_DSS_ROT_270: - vidrot = 3; + case DRM_MODE_ROTATE_270: + vidrot = 1; break; } } - if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270) + if (drm_rotation_90_or_270(rotation)) row_repeat = true; else row_repeat = false; @@ -1855,53 +1947,46 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane_id plane, u8 rotation, * NV12 in 1D mode must use ROTATION=1. Otherwise DSS will fetch extra * rows beyond the framebuffer, which may cause OCP error. */ - if (color_mode == OMAP_DSS_COLOR_NV12 && - rotation_type != OMAP_DSS_ROT_TILER) + if (fourcc == DRM_FORMAT_NV12 && rotation_type != OMAP_DSS_ROT_TILER) vidrot = 1; REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), vidrot, 13, 12); - if (dss_has_feature(FEAT_ROWREPEATENABLE)) + if (dispc_has_feature(FEAT_ROWREPEATENABLE)) REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), row_repeat ? 1 : 0, 18, 18); - if (color_mode == OMAP_DSS_COLOR_NV12) { - bool doublestride = (rotation_type == OMAP_DSS_ROT_TILER) && - (rotation == OMAP_DSS_ROT_0 || - rotation == OMAP_DSS_ROT_180); + if (dispc_ovl_color_mode_supported(plane, DRM_FORMAT_NV12)) { + bool doublestride = + fourcc == DRM_FORMAT_NV12 && + rotation_type == OMAP_DSS_ROT_TILER && + !drm_rotation_90_or_270(rotation); + /* DOUBLESTRIDE */ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), doublestride, 22, 22); } - } -static int color_mode_to_bpp(enum omap_color_mode color_mode) +static int color_mode_to_bpp(u32 fourcc) { - switch (color_mode) { - case OMAP_DSS_COLOR_CLUT1: - return 1; - case OMAP_DSS_COLOR_CLUT2: - return 2; - case OMAP_DSS_COLOR_CLUT4: - return 4; - case OMAP_DSS_COLOR_CLUT8: - case OMAP_DSS_COLOR_NV12: + switch (fourcc) { + case DRM_FORMAT_NV12: return 8; - case OMAP_DSS_COLOR_RGB12U: - case OMAP_DSS_COLOR_RGB16: - case OMAP_DSS_COLOR_ARGB16: - case OMAP_DSS_COLOR_YUV2: - case OMAP_DSS_COLOR_UYVY: - case OMAP_DSS_COLOR_RGBA16: - case OMAP_DSS_COLOR_RGBX16: - case OMAP_DSS_COLOR_ARGB16_1555: - case OMAP_DSS_COLOR_XRGB16_1555: + case DRM_FORMAT_RGBX4444: + case DRM_FORMAT_RGB565: + case DRM_FORMAT_ARGB4444: + case DRM_FORMAT_YUYV: + case DRM_FORMAT_UYVY: + case DRM_FORMAT_RGBA4444: + case DRM_FORMAT_XRGB4444: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_XRGB1555: return 16; - case OMAP_DSS_COLOR_RGB24P: + case DRM_FORMAT_RGB888: return 24; - case OMAP_DSS_COLOR_RGB24U: - case OMAP_DSS_COLOR_ARGB32: - case OMAP_DSS_COLOR_RGBA32: - case OMAP_DSS_COLOR_RGBX32: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_RGBX8888: return 32; default: BUG(); @@ -1922,281 +2007,42 @@ static s32 pixinc(int pixels, u8 ps) return 0; } -static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, - u16 screen_width, - u16 width, u16 height, - enum omap_color_mode color_mode, bool fieldmode, - unsigned int field_offset, - unsigned *offset0, unsigned *offset1, - s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) +static void calc_offset(u16 screen_width, u16 width, + u32 fourcc, bool fieldmode, + unsigned int field_offset, unsigned *offset0, unsigned *offset1, + s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim, + enum omap_dss_rotation_type rotation_type, u8 rotation) { u8 ps; - /* FIXME CLUT formats */ - switch (color_mode) { - case OMAP_DSS_COLOR_CLUT1: - case OMAP_DSS_COLOR_CLUT2: - case OMAP_DSS_COLOR_CLUT4: - case OMAP_DSS_COLOR_CLUT8: - BUG(); - return; - case OMAP_DSS_COLOR_YUV2: - case OMAP_DSS_COLOR_UYVY: - ps = 4; - break; - default: - ps = color_mode_to_bpp(color_mode) / 8; - break; - } + ps = color_mode_to_bpp(fourcc) / 8; - DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width, - width, height); + DSSDBG("scrw %d, width %d\n", screen_width, width); - /* - * field 0 = even field = bottom field - * field 1 = odd field = top field - */ - switch (rotation + mirror * 4) { - case OMAP_DSS_ROT_0: - case OMAP_DSS_ROT_180: + if (rotation_type == OMAP_DSS_ROT_TILER && + (fourcc == DRM_FORMAT_UYVY || fourcc == DRM_FORMAT_YUYV) && + drm_rotation_90_or_270(rotation)) { /* - * If the pixel format is YUV or UYVY divide the width - * of the image by 2 for 0 and 180 degree rotation. + * HACK: ROW_INC needs to be calculated with TILER units. + * We get such 'screen_width' that multiplying it with the + * YUV422 pixel size gives the correct TILER container width. + * However, 'width' is in pixels and multiplying it with YUV422 + * pixel size gives incorrect result. We thus multiply it here + * with 2 to match the 32 bit TILER unit size. */ - if (color_mode == OMAP_DSS_COLOR_YUV2 || - color_mode == OMAP_DSS_COLOR_UYVY) - width = width >> 1; - case OMAP_DSS_ROT_90: - case OMAP_DSS_ROT_270: - *offset1 = 0; - if (field_offset) - *offset0 = field_offset * screen_width * ps; - else - *offset0 = 0; - - *row_inc = pixinc(1 + - (y_predecim * screen_width - x_predecim * width) + - (fieldmode ? screen_width : 0), ps); - *pix_inc = pixinc(x_predecim, ps); - break; - - case OMAP_DSS_ROT_0 + 4: - case OMAP_DSS_ROT_180 + 4: - /* If the pixel format is YUV or UYVY divide the width - * of the image by 2 for 0 degree and 180 degree - */ - if (color_mode == OMAP_DSS_COLOR_YUV2 || - color_mode == OMAP_DSS_COLOR_UYVY) - width = width >> 1; - case OMAP_DSS_ROT_90 + 4: - case OMAP_DSS_ROT_270 + 4: - *offset1 = 0; - if (field_offset) - *offset0 = field_offset * screen_width * ps; - else - *offset0 = 0; - *row_inc = pixinc(1 - - (y_predecim * screen_width + x_predecim * width) - - (fieldmode ? screen_width : 0), ps); - *pix_inc = pixinc(x_predecim, ps); - break; - - default: - BUG(); - return; - } -} - -static void calc_dma_rotation_offset(u8 rotation, bool mirror, - u16 screen_width, - u16 width, u16 height, - enum omap_color_mode color_mode, bool fieldmode, - unsigned int field_offset, - unsigned *offset0, unsigned *offset1, - s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) -{ - u8 ps; - u16 fbw, fbh; - - /* FIXME CLUT formats */ - switch (color_mode) { - case OMAP_DSS_COLOR_CLUT1: - case OMAP_DSS_COLOR_CLUT2: - case OMAP_DSS_COLOR_CLUT4: - case OMAP_DSS_COLOR_CLUT8: - BUG(); - return; - default: - ps = color_mode_to_bpp(color_mode) / 8; - break; - } - - DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width, - width, height); - - /* width & height are overlay sizes, convert to fb sizes */ - - if (rotation == OMAP_DSS_ROT_0 || rotation == OMAP_DSS_ROT_180) { - fbw = width; - fbh = height; - } else { - fbw = height; - fbh = width; + width *= 2; } /* * field 0 = even field = bottom field * field 1 = odd field = top field */ - switch (rotation + mirror * 4) { - case OMAP_DSS_ROT_0: - *offset1 = 0; - if (field_offset) - *offset0 = *offset1 + field_offset * screen_width * ps; - else - *offset0 = *offset1; - *row_inc = pixinc(1 + - (y_predecim * screen_width - fbw * x_predecim) + - (fieldmode ? screen_width : 0), ps); - if (color_mode == OMAP_DSS_COLOR_YUV2 || - color_mode == OMAP_DSS_COLOR_UYVY) - *pix_inc = pixinc(x_predecim, 2 * ps); - else - *pix_inc = pixinc(x_predecim, ps); - break; - case OMAP_DSS_ROT_90: - *offset1 = screen_width * (fbh - 1) * ps; - if (field_offset) - *offset0 = *offset1 + field_offset * ps; - else - *offset0 = *offset1; - *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) + - y_predecim + (fieldmode ? 1 : 0), ps); - *pix_inc = pixinc(-x_predecim * screen_width, ps); - break; - case OMAP_DSS_ROT_180: - *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; - if (field_offset) - *offset0 = *offset1 - field_offset * screen_width * ps; - else - *offset0 = *offset1; - *row_inc = pixinc(-1 - - (y_predecim * screen_width - fbw * x_predecim) - - (fieldmode ? screen_width : 0), ps); - if (color_mode == OMAP_DSS_COLOR_YUV2 || - color_mode == OMAP_DSS_COLOR_UYVY) - *pix_inc = pixinc(-x_predecim, 2 * ps); - else - *pix_inc = pixinc(-x_predecim, ps); - break; - case OMAP_DSS_ROT_270: - *offset1 = (fbw - 1) * ps; - if (field_offset) - *offset0 = *offset1 - field_offset * ps; - else - *offset0 = *offset1; - *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) - - y_predecim - (fieldmode ? 1 : 0), ps); - *pix_inc = pixinc(x_predecim * screen_width, ps); - break; - - /* mirroring */ - case OMAP_DSS_ROT_0 + 4: - *offset1 = (fbw - 1) * ps; - if (field_offset) - *offset0 = *offset1 + field_offset * screen_width * ps; - else - *offset0 = *offset1; - *row_inc = pixinc(y_predecim * screen_width * 2 - 1 + - (fieldmode ? screen_width : 0), - ps); - if (color_mode == OMAP_DSS_COLOR_YUV2 || - color_mode == OMAP_DSS_COLOR_UYVY) - *pix_inc = pixinc(-x_predecim, 2 * ps); - else - *pix_inc = pixinc(-x_predecim, ps); - break; - - case OMAP_DSS_ROT_90 + 4: - *offset1 = 0; - if (field_offset) - *offset0 = *offset1 + field_offset * ps; - else - *offset0 = *offset1; - *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) + - y_predecim + (fieldmode ? 1 : 0), - ps); - *pix_inc = pixinc(x_predecim * screen_width, ps); - break; - - case OMAP_DSS_ROT_180 + 4: - *offset1 = screen_width * (fbh - 1) * ps; - if (field_offset) - *offset0 = *offset1 - field_offset * screen_width * ps; - else - *offset0 = *offset1; - *row_inc = pixinc(1 - y_predecim * screen_width * 2 - - (fieldmode ? screen_width : 0), - ps); - if (color_mode == OMAP_DSS_COLOR_YUV2 || - color_mode == OMAP_DSS_COLOR_UYVY) - *pix_inc = pixinc(x_predecim, 2 * ps); - else - *pix_inc = pixinc(x_predecim, ps); - break; - - case OMAP_DSS_ROT_270 + 4: - *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; - if (field_offset) - *offset0 = *offset1 - field_offset * ps; - else - *offset0 = *offset1; - *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) - - y_predecim - (fieldmode ? 1 : 0), - ps); - *pix_inc = pixinc(-x_predecim * screen_width, ps); - break; - - default: - BUG(); - return; - } -} - -static void calc_tiler_rotation_offset(u16 screen_width, u16 width, - enum omap_color_mode color_mode, bool fieldmode, - unsigned int field_offset, unsigned *offset0, unsigned *offset1, - s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) -{ - u8 ps; - - switch (color_mode) { - case OMAP_DSS_COLOR_CLUT1: - case OMAP_DSS_COLOR_CLUT2: - case OMAP_DSS_COLOR_CLUT4: - case OMAP_DSS_COLOR_CLUT8: - BUG(); - return; - default: - ps = color_mode_to_bpp(color_mode) / 8; - break; - } - - DSSDBG("scrw %d, width %d\n", screen_width, width); - - /* - * field 0 = even field = bottom field - * field 1 = odd field = top field - */ + *offset0 = field_offset * screen_width * ps; *offset1 = 0; - if (field_offset) - *offset0 = *offset1 + field_offset * screen_width * ps; - else - *offset0 = *offset1; + *row_inc = pixinc(1 + (y_predecim * screen_width - width * x_predecim) + (fieldmode ? screen_width : 0), ps); - if (color_mode == OMAP_DSS_COLOR_YUV2 || - color_mode == OMAP_DSS_COLOR_UYVY) + if (fourcc == DRM_FORMAT_YUYV || fourcc == DRM_FORMAT_UYVY) *pix_inc = pixinc(x_predecim, 2 * ps); else *pix_inc = pixinc(x_predecim, ps); @@ -2263,7 +2109,7 @@ static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk, static unsigned long calc_core_clk_five_taps(unsigned long pclk, const struct videomode *vm, u16 width, u16 height, u16 out_width, u16 out_height, - enum omap_color_mode color_mode) + u32 fourcc) { u32 core_clk = 0; u64 tmp; @@ -2293,7 +2139,7 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk, do_div(tmp, out_width); core_clk = max_t(u32, core_clk, tmp); - if (color_mode == OMAP_DSS_COLOR_RGB24U) + if (fourcc == DRM_FORMAT_XRGB8888) core_clk <<= 1; } @@ -2356,15 +2202,14 @@ static unsigned long calc_core_clk_44xx(unsigned long pclk, u16 width, static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk, const struct videomode *vm, u16 width, u16 height, u16 out_width, u16 out_height, - enum omap_color_mode color_mode, bool *five_taps, + u32 fourcc, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, u16 pos_x, unsigned long *core_clk, bool mem_to_mem) { int error; u16 in_width, in_height; int min_factor = min(*decim_x, *decim_y); - const int maxsinglelinewidth = - dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); + const int maxsinglelinewidth = dispc.feat->max_line_width; *five_taps = false; @@ -2402,14 +2247,13 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk, static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, const struct videomode *vm, u16 width, u16 height, u16 out_width, u16 out_height, - enum omap_color_mode color_mode, bool *five_taps, + u32 fourcc, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, u16 pos_x, unsigned long *core_clk, bool mem_to_mem) { int error; u16 in_width, in_height; - const int maxsinglelinewidth = - dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); + const int maxsinglelinewidth = dispc.feat->max_line_width; do { in_height = height / *decim_y; @@ -2424,7 +2268,7 @@ again: if (*five_taps) *core_clk = calc_core_clk_five_taps(pclk, vm, in_width, in_height, out_width, - out_height, color_mode); + out_height, fourcc); else *core_clk = dispc.feat->calc_core_clk(pclk, in_width, in_height, out_width, out_height, @@ -2487,16 +2331,15 @@ again: static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, const struct videomode *vm, u16 width, u16 height, u16 out_width, u16 out_height, - enum omap_color_mode color_mode, bool *five_taps, + u32 fourcc, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, u16 pos_x, unsigned long *core_clk, bool mem_to_mem) { u16 in_width, in_width_max; int decim_x_min = *decim_x; u16 in_height = height / *decim_y; - const int maxsinglelinewidth = - dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); - const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); + const int maxsinglelinewidth = dispc.feat->max_line_width; + const int maxdownscale = dispc.feat->max_downscale; if (mem_to_mem) { in_width_max = out_width * maxdownscale; @@ -2521,7 +2364,7 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, return -EINVAL; } - if (*decim_x > 4 && color_mode != OMAP_DSS_COLOR_NV12) { + if (*decim_x > 4 && fourcc != DRM_FORMAT_NV12) { /* * Let's disable all scaling that requires horizontal * decimation with higher factor than 4, until we have @@ -2552,11 +2395,11 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, enum omap_overlay_caps caps, const struct videomode *vm, u16 width, u16 height, u16 out_width, u16 out_height, - enum omap_color_mode color_mode, bool *five_taps, + u32 fourcc, bool *five_taps, int *x_predecim, int *y_predecim, u16 pos_x, enum omap_dss_rotation_type rotation_type, bool mem_to_mem) { - const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); + const int maxdownscale = dispc.feat->max_downscale; const int max_decim_limit = 16; unsigned long core_clk = 0; int decim_x, decim_y, ret; @@ -2577,20 +2420,10 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, } else { *x_predecim = max_decim_limit; *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER && - dss_has_feature(FEAT_BURST_2D)) ? + dispc_has_feature(FEAT_BURST_2D)) ? 2 : max_decim_limit; } - if (color_mode == OMAP_DSS_COLOR_CLUT1 || - color_mode == OMAP_DSS_COLOR_CLUT2 || - color_mode == OMAP_DSS_COLOR_CLUT4 || - color_mode == OMAP_DSS_COLOR_CLUT8) { - *x_predecim = 1; - *y_predecim = 1; - *five_taps = false; - return 0; - } - decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale); decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale); @@ -2601,7 +2434,7 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, return -EINVAL; ret = dispc.feat->calc_scaling(pclk, lclk, vm, width, height, - out_width, out_height, color_mode, five_taps, + out_width, out_height, fourcc, five_taps, x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk, mem_to_mem); if (ret) @@ -2637,8 +2470,8 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, static int dispc_ovl_setup_common(enum omap_plane_id plane, enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr, u16 screen_width, int pos_x, int pos_y, u16 width, u16 height, - u16 out_width, u16 out_height, enum omap_color_mode color_mode, - u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha, + u16 out_width, u16 out_height, u32 fourcc, + u8 rotation, u8 zorder, u8 pre_mult_alpha, u8 global_alpha, enum omap_dss_rotation_type rotation_type, bool replication, const struct videomode *vm, bool mem_to_mem) @@ -2661,19 +2494,9 @@ static int dispc_ovl_setup_common(enum omap_plane_id plane, if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER) return -EINVAL; - switch (color_mode) { - case OMAP_DSS_COLOR_YUV2: - case OMAP_DSS_COLOR_UYVY: - case OMAP_DSS_COLOR_NV12: - if (in_width & 1) { - DSSERR("input width %d is not even for YUV format\n", - in_width); - return -EINVAL; - } - break; - - default: - break; + if (format_is_yuv(fourcc) && (in_width & 1)) { + DSSERR("input width %d is not even for YUV format\n", in_width); + return -EINVAL; } out_width = out_width == 0 ? width : out_width; @@ -2693,11 +2516,11 @@ static int dispc_ovl_setup_common(enum omap_plane_id plane, out_height); } - if (!dss_feat_color_mode_supported(plane, color_mode)) + if (!dispc_ovl_color_mode_supported(plane, fourcc)) return -EINVAL; r = dispc_ovl_calc_scaling(pclk, lclk, caps, vm, in_width, - in_height, out_width, out_height, color_mode, + in_height, out_width, out_height, fourcc, &five_taps, &x_predecim, &y_predecim, pos_x, rotation_type, mem_to_mem); if (r) @@ -2710,26 +2533,15 @@ static int dispc_ovl_setup_common(enum omap_plane_id plane, DSSDBG("predecimation %d x %x, new input size %d x %d\n", x_predecim, y_predecim, in_width, in_height); - switch (color_mode) { - case OMAP_DSS_COLOR_YUV2: - case OMAP_DSS_COLOR_UYVY: - case OMAP_DSS_COLOR_NV12: - if (in_width & 1) { - DSSDBG("predecimated input width is not even for YUV format\n"); - DSSDBG("adjusting input width %d -> %d\n", - in_width, in_width & ~1); + if (format_is_yuv(fourcc) && (in_width & 1)) { + DSSDBG("predecimated input width is not even for YUV format\n"); + DSSDBG("adjusting input width %d -> %d\n", + in_width, in_width & ~1); - in_width &= ~1; - } - break; - - default: - break; + in_width &= ~1; } - if (color_mode == OMAP_DSS_COLOR_YUV2 || - color_mode == OMAP_DSS_COLOR_UYVY || - color_mode == OMAP_DSS_COLOR_NV12) + if (format_is_yuv(fourcc)) cconv = 1; if (ilace && !fieldmode) { @@ -2763,28 +2575,16 @@ static int dispc_ovl_setup_common(enum omap_plane_id plane, frame_height = height; } - if (rotation_type == OMAP_DSS_ROT_TILER) - calc_tiler_rotation_offset(screen_width, frame_width, - color_mode, fieldmode, field_offset, - &offset0, &offset1, &row_inc, &pix_inc, - x_predecim, y_predecim); - else if (rotation_type == OMAP_DSS_ROT_DMA) - calc_dma_rotation_offset(rotation, mirror, screen_width, - frame_width, frame_height, - color_mode, fieldmode, field_offset, - &offset0, &offset1, &row_inc, &pix_inc, - x_predecim, y_predecim); - else - calc_vrfb_rotation_offset(rotation, mirror, - screen_width, frame_width, frame_height, - color_mode, fieldmode, field_offset, - &offset0, &offset1, &row_inc, &pix_inc, - x_predecim, y_predecim); + calc_offset(screen_width, frame_width, + fourcc, fieldmode, field_offset, + &offset0, &offset1, &row_inc, &pix_inc, + x_predecim, y_predecim, + rotation_type, rotation); DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", offset0, offset1, row_inc, pix_inc); - dispc_ovl_set_color_mode(plane, color_mode); + dispc_ovl_set_color_mode(plane, fourcc); dispc_ovl_configure_burst_type(plane, rotation_type); @@ -2794,7 +2594,7 @@ static int dispc_ovl_setup_common(enum omap_plane_id plane, dispc_ovl_set_ba0(plane, paddr + offset0); dispc_ovl_set_ba1(plane, paddr + offset1); - if (OMAP_DSS_COLOR_NV12 == color_mode) { + if (fourcc == DRM_FORMAT_NV12) { dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0); dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1); } @@ -2815,13 +2615,12 @@ static int dispc_ovl_setup_common(enum omap_plane_id plane, if (caps & OMAP_DSS_OVL_CAP_SCALE) { dispc_ovl_set_scaling(plane, in_width, in_height, out_width, out_height, ilace, five_taps, fieldmode, - color_mode, rotation); + fourcc, rotation); dispc_ovl_set_output_size(plane, out_width, out_height); dispc_ovl_set_vid_color_conv(plane, cconv); } - dispc_ovl_set_rotation_attrs(plane, rotation, rotation_type, mirror, - color_mode); + dispc_ovl_set_rotation_attrs(plane, rotation, rotation_type, fourcc); dispc_ovl_set_zorder(plane, caps, zorder); dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha); @@ -2834,25 +2633,25 @@ static int dispc_ovl_setup_common(enum omap_plane_id plane, static int dispc_ovl_setup(enum omap_plane_id plane, const struct omap_overlay_info *oi, - const struct videomode *vm, bool mem_to_mem) + const struct videomode *vm, bool mem_to_mem, + enum omap_channel channel) { int r; - enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane); - enum omap_channel channel; + enum omap_overlay_caps caps = dispc.feat->overlay_caps[plane]; const bool replication = true; - channel = dispc_ovl_get_channel_out(plane); - DSSDBG("dispc_ovl_setup %d, pa %pad, pa_uv %pad, sw %d, %d,%d, %dx%d ->" - " %dx%d, cmode %x, rot %d, mir %d, chan %d repl %d\n", + " %dx%d, cmode %x, rot %d, chan %d repl %d\n", plane, &oi->paddr, &oi->p_uv_addr, oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height, - oi->color_mode, oi->rotation, oi->mirror, channel, replication); + oi->fourcc, oi->rotation, channel, replication); + + dispc_ovl_set_channel_out(plane, channel); r = dispc_ovl_setup_common(plane, caps, oi->paddr, oi->p_uv_addr, oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height, - oi->out_width, oi->out_height, oi->color_mode, oi->rotation, - oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha, + oi->out_width, oi->out_height, oi->fourcc, oi->rotation, + oi->zorder, oi->pre_mult_alpha, oi->global_alpha, oi->rotation_type, replication, vm, mem_to_mem); return r; @@ -2874,25 +2673,24 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi, OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA; DSSDBG("dispc_wb_setup, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, " - "rot %d, mir %d\n", wi->paddr, wi->p_uv_addr, in_width, - in_height, wi->width, wi->height, wi->color_mode, wi->rotation, - wi->mirror); + "rot %d\n", wi->paddr, wi->p_uv_addr, in_width, + in_height, wi->width, wi->height, wi->fourcc, wi->rotation); r = dispc_ovl_setup_common(plane, caps, wi->paddr, wi->p_uv_addr, wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width, - wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder, + wi->height, wi->fourcc, wi->rotation, zorder, wi->pre_mult_alpha, global_alpha, wi->rotation_type, replication, vm, mem_to_mem); - switch (wi->color_mode) { - case OMAP_DSS_COLOR_RGB16: - case OMAP_DSS_COLOR_RGB24P: - case OMAP_DSS_COLOR_ARGB16: - case OMAP_DSS_COLOR_RGBA16: - case OMAP_DSS_COLOR_RGB12U: - case OMAP_DSS_COLOR_ARGB16_1555: - case OMAP_DSS_COLOR_XRGB16_1555: - case OMAP_DSS_COLOR_RGBX16: + switch (wi->fourcc) { + case DRM_FORMAT_RGB565: + case DRM_FORMAT_RGB888: + case DRM_FORMAT_ARGB4444: + case DRM_FORMAT_RGBA4444: + case DRM_FORMAT_RGBX4444: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_XRGB4444: truncation = true; break; default: @@ -2935,19 +2733,14 @@ static int dispc_ovl_enable(enum omap_plane_id plane, bool enable) return 0; } -static bool dispc_ovl_enabled(enum omap_plane_id plane) -{ - return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0); -} - static enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channel) { - return dss_feat_get_supported_outputs(channel); + return dss_get_supported_outputs(channel); } static void dispc_lcd_enable_signal_polarity(bool act_high) { - if (!dss_has_feature(FEAT_LCDENABLEPOL)) + if (!dispc_has_feature(FEAT_LCDENABLEPOL)) return; REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); @@ -2955,7 +2748,7 @@ static void dispc_lcd_enable_signal_polarity(bool act_high) void dispc_lcd_enable_signal(bool enable) { - if (!dss_has_feature(FEAT_LCDENABLESIGNAL)) + if (!dispc_has_feature(FEAT_LCDENABLESIGNAL)) return; REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); @@ -2963,17 +2756,12 @@ void dispc_lcd_enable_signal(bool enable) void dispc_pck_free_enable(bool enable) { - if (!dss_has_feature(FEAT_PCKFREEENABLE)) + if (!dispc_has_feature(FEAT_PCKFREEENABLE)) return; REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); } -static int dispc_get_num_mgrs(void) -{ - return dss_feat_get_num_mgrs(); -} - static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable) { mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable); @@ -3013,7 +2801,7 @@ static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable) static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable) { - if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) + if (!dispc_has_feature(FEAT_ALPHA_FIXED_ZORDER)) return; if (ch == OMAP_DSS_CHANNEL_LCD) @@ -3030,7 +2818,7 @@ static void dispc_mgr_setup(enum omap_channel channel, dispc_mgr_enable_trans_key(channel, info->trans_enabled); dispc_mgr_enable_alpha_fixed_zorder(channel, info->partial_alpha_enabled); - if (dss_has_feature(FEAT_CPR)) { + if (dispc_has_feature(FEAT_CPR)) { dispc_mgr_enable_cpr(channel, info->cpr_enable); dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs); } @@ -3308,7 +3096,7 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, dispc_write_reg(DISPC_DIVISORo(channel), FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); - if (!dss_has_feature(FEAT_CORE_CLK_DIV) && + if (!dispc_has_feature(FEAT_CORE_CLK_DIV) && channel == OMAP_DSS_CHANNEL_LCD) dispc.core_clk_rate = dispc_fclk_rate() / lck_div; } @@ -3463,7 +3251,7 @@ void dispc_dump_clocks(struct seq_file *s) seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); - if (dss_has_feature(FEAT_CORE_CLK_DIV)) { + if (dispc_has_feature(FEAT_CORE_CLK_DIV)) { seq_printf(s, "- DISPC-CORE-CLK -\n"); l = dispc_read_reg(DISPC_DIVISOR); lcd = FLD_GET(l, 23, 16); @@ -3474,9 +3262,9 @@ void dispc_dump_clocks(struct seq_file *s) dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD); - if (dss_has_feature(FEAT_MGR_LCD2)) + if (dispc_has_feature(FEAT_MGR_LCD2)) dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD2); - if (dss_has_feature(FEAT_MGR_LCD3)) + if (dispc_has_feature(FEAT_MGR_LCD3)) dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD3); dispc_runtime_put(); @@ -3516,18 +3304,18 @@ static void dispc_dump_regs(struct seq_file *s) DUMPREG(DISPC_CAPABLE); DUMPREG(DISPC_LINE_STATUS); DUMPREG(DISPC_LINE_NUMBER); - if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || - dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) + if (dispc_has_feature(FEAT_ALPHA_FIXED_ZORDER) || + dispc_has_feature(FEAT_ALPHA_FREE_ZORDER)) DUMPREG(DISPC_GLOBAL_ALPHA); - if (dss_has_feature(FEAT_MGR_LCD2)) { + if (dispc_has_feature(FEAT_MGR_LCD2)) { DUMPREG(DISPC_CONTROL2); DUMPREG(DISPC_CONFIG2); } - if (dss_has_feature(FEAT_MGR_LCD3)) { + if (dispc_has_feature(FEAT_MGR_LCD3)) { DUMPREG(DISPC_CONTROL3); DUMPREG(DISPC_CONFIG3); } - if (dss_has_feature(FEAT_MFLAG)) + if (dispc_has_feature(FEAT_MFLAG)) DUMPREG(DISPC_GLOBAL_MFLAG_ATTRIBUTE); #undef DUMPREG @@ -3540,7 +3328,7 @@ static void dispc_dump_regs(struct seq_file *s) p_names = mgr_names; /* DISPC channel specific registers */ - for (i = 0; i < dss_feat_get_num_mgrs(); i++) { + for (i = 0; i < dispc_get_num_mgrs(); i++) { DUMPREG(i, DISPC_DEFAULT_COLOR); DUMPREG(i, DISPC_TRANS_COLOR); DUMPREG(i, DISPC_SIZE_MGR); @@ -3557,7 +3345,7 @@ static void dispc_dump_regs(struct seq_file *s) DUMPREG(i, DISPC_DATA_CYCLE2); DUMPREG(i, DISPC_DATA_CYCLE3); - if (dss_has_feature(FEAT_CPR)) { + if (dispc_has_feature(FEAT_CPR)) { DUMPREG(i, DISPC_CPR_COEF_R); DUMPREG(i, DISPC_CPR_COEF_G); DUMPREG(i, DISPC_CPR_COEF_B); @@ -3566,7 +3354,7 @@ static void dispc_dump_regs(struct seq_file *s) p_names = ovl_names; - for (i = 0; i < dss_feat_get_num_ovls(); i++) { + for (i = 0; i < dispc_get_num_ovls(); i++) { DUMPREG(i, DISPC_OVL_BA0); DUMPREG(i, DISPC_OVL_BA1); DUMPREG(i, DISPC_OVL_POSITION); @@ -3577,9 +3365,9 @@ static void dispc_dump_regs(struct seq_file *s) DUMPREG(i, DISPC_OVL_ROW_INC); DUMPREG(i, DISPC_OVL_PIXEL_INC); - if (dss_has_feature(FEAT_PRELOAD)) + if (dispc_has_feature(FEAT_PRELOAD)) DUMPREG(i, DISPC_OVL_PRELOAD); - if (dss_has_feature(FEAT_MFLAG)) + if (dispc_has_feature(FEAT_MFLAG)) DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD); if (i == OMAP_DSS_GFX) { @@ -3592,14 +3380,14 @@ static void dispc_dump_regs(struct seq_file *s) DUMPREG(i, DISPC_OVL_PICTURE_SIZE); DUMPREG(i, DISPC_OVL_ACCU0); DUMPREG(i, DISPC_OVL_ACCU1); - if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { + if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) { DUMPREG(i, DISPC_OVL_BA0_UV); DUMPREG(i, DISPC_OVL_BA1_UV); DUMPREG(i, DISPC_OVL_FIR2); DUMPREG(i, DISPC_OVL_ACCU2_0); DUMPREG(i, DISPC_OVL_ACCU2_1); } - if (dss_has_feature(FEAT_ATTR2)) + if (dispc_has_feature(FEAT_ATTR2)) DUMPREG(i, DISPC_OVL_ATTRIBUTES2); } @@ -3614,21 +3402,21 @@ static void dispc_dump_regs(struct seq_file *s) DUMPREG(i, DISPC_OVL_ROW_INC); DUMPREG(i, DISPC_OVL_PIXEL_INC); - if (dss_has_feature(FEAT_MFLAG)) + if (dispc_has_feature(FEAT_MFLAG)) DUMPREG(i, DISPC_OVL_MFLAG_THRESHOLD); DUMPREG(i, DISPC_OVL_FIR); DUMPREG(i, DISPC_OVL_PICTURE_SIZE); DUMPREG(i, DISPC_OVL_ACCU0); DUMPREG(i, DISPC_OVL_ACCU1); - if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { + if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) { DUMPREG(i, DISPC_OVL_BA0_UV); DUMPREG(i, DISPC_OVL_BA1_UV); DUMPREG(i, DISPC_OVL_FIR2); DUMPREG(i, DISPC_OVL_ACCU2_0); DUMPREG(i, DISPC_OVL_ACCU2_1); } - if (dss_has_feature(FEAT_ATTR2)) + if (dispc_has_feature(FEAT_ATTR2)) DUMPREG(i, DISPC_OVL_ATTRIBUTES2); } @@ -3644,7 +3432,7 @@ static void dispc_dump_regs(struct seq_file *s) /* Video pipeline coefficient registers */ /* start from OMAP_DSS_VIDEO1 */ - for (i = 1; i < dss_feat_get_num_ovls(); i++) { + for (i = 1; i < dispc_get_num_ovls(); i++) { for (j = 0; j < 8; j++) DUMPREG(i, DISPC_OVL_FIR_COEF_H, j); @@ -3654,12 +3442,12 @@ static void dispc_dump_regs(struct seq_file *s) for (j = 0; j < 5; j++) DUMPREG(i, DISPC_OVL_CONV_COEF, j); - if (dss_has_feature(FEAT_FIR_COEF_V)) { + if (dispc_has_feature(FEAT_FIR_COEF_V)) { for (j = 0; j < 8; j++) DUMPREG(i, DISPC_OVL_FIR_COEF_V, j); } - if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { + if (dispc_has_feature(FEAT_HANDLE_UV_SEPARATE)) { for (j = 0; j < 8; j++) DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j); @@ -3692,7 +3480,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, return 0; } -bool dispc_div_calc(unsigned long dispc, +bool dispc_div_calc(unsigned long dispc_freq, unsigned long pck_min, unsigned long pck_max, dispc_div_calc_func func, void *data) { @@ -3710,19 +3498,19 @@ bool dispc_div_calc(unsigned long dispc, min_fck_per_pck = 0; #endif - pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD); - pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD); + pckd_hw_min = dispc.feat->min_pcd; + pckd_hw_max = 255; - lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); + lck_max = dss_get_max_fck_rate(); pck_min = pck_min ? pck_min : 1; pck_max = pck_max ? pck_max : ULONG_MAX; - lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul); - lckd_stop = min(dispc / pck_min, 255ul); + lckd_start = max(DIV_ROUND_UP(dispc_freq, lck_max), 1ul); + lckd_stop = min(dispc_freq / pck_min, 255ul); for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) { - lck = dispc / lckd; + lck = dispc_freq / lckd; pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min); pckd_stop = min(lck / pck_min, pckd_hw_max); @@ -3736,7 +3524,7 @@ bool dispc_div_calc(unsigned long dispc, * also. Thus we need to use the calculated lck. For * OMAP4+ the DISPC fclk is a separate clock. */ - if (dss_has_feature(FEAT_CORE_CLK_DIV)) + if (dispc_has_feature(FEAT_CORE_CLK_DIV)) fck = dispc_core_clk_rate(); else fck = lck; @@ -3787,11 +3575,6 @@ static void dispc_clear_irqstatus(u32 mask) dispc_write_reg(DISPC_IRQSTATUS, mask); } -static u32 dispc_read_irqenable(void) -{ - return dispc_read_reg(DISPC_IRQENABLE); -} - static void dispc_write_irqenable(u32 mask) { u32 old_mask = dispc_read_reg(DISPC_IRQENABLE); @@ -3800,6 +3583,9 @@ static void dispc_write_irqenable(u32 mask) dispc_clear_irqstatus((mask ^ old_mask) & mask); dispc_write_reg(DISPC_IRQENABLE, mask); + + /* flush posted write */ + dispc_read_reg(DISPC_IRQENABLE); } void dispc_enable_sidle(void) @@ -3853,10 +3639,10 @@ static void dispc_restore_gamma_tables(void) dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_DIGIT); - if (dss_has_feature(FEAT_MGR_LCD2)) + if (dispc_has_feature(FEAT_MGR_LCD2)) dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD2); - if (dss_has_feature(FEAT_MGR_LCD3)) + if (dispc_has_feature(FEAT_MGR_LCD3)) dispc_mgr_write_gamma_table(OMAP_DSS_CHANNEL_LCD3); } @@ -3924,11 +3710,11 @@ static int dispc_init_gamma_tables(void) u32 *gt; if (channel == OMAP_DSS_CHANNEL_LCD2 && - !dss_has_feature(FEAT_MGR_LCD2)) + !dispc_has_feature(FEAT_MGR_LCD2)) continue; if (channel == OMAP_DSS_CHANNEL_LCD3 && - !dss_has_feature(FEAT_MGR_LCD3)) + !dispc_has_feature(FEAT_MGR_LCD3)) continue; gt = devm_kmalloc_array(&dispc.pdev->dev, gdesc->len, @@ -3948,7 +3734,7 @@ static void _omap_dispc_initial_config(void) u32 l; /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */ - if (dss_has_feature(FEAT_CORE_CLK_DIV)) { + if (dispc_has_feature(FEAT_CORE_CLK_DIV)) { l = dispc_read_reg(DISPC_DIVISOR); /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */ l = FLD_MOD(l, 1, 0, 0); @@ -3966,7 +3752,7 @@ static void _omap_dispc_initial_config(void) * func-clock auto-gating. For newer versions * (dispc.feat->has_gamma_table) this enables tv-out gamma tables. */ - if (dss_has_feature(FEAT_FUNCGATED) || dispc.feat->has_gamma_table) + if (dispc_has_feature(FEAT_FUNCGATED) || dispc.feat->has_gamma_table) REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); dispc_setup_color_conv_coef(); @@ -3982,10 +3768,272 @@ static void _omap_dispc_initial_config(void) if (dispc.feat->mstandby_workaround) REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0); - if (dss_has_feature(FEAT_MFLAG)) + if (dispc_has_feature(FEAT_MFLAG)) dispc_init_mflag(); } +static const enum dispc_feature_id omap2_dispc_features_list[] = { + FEAT_LCDENABLEPOL, + FEAT_LCDENABLESIGNAL, + FEAT_PCKFREEENABLE, + FEAT_FUNCGATED, + FEAT_ROWREPEATENABLE, + FEAT_RESIZECONF, +}; + +static const enum dispc_feature_id omap3_dispc_features_list[] = { + FEAT_LCDENABLEPOL, + FEAT_LCDENABLESIGNAL, + FEAT_PCKFREEENABLE, + FEAT_FUNCGATED, + FEAT_LINEBUFFERSPLIT, + FEAT_ROWREPEATENABLE, + FEAT_RESIZECONF, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FIXED_ZORDER, + FEAT_FIFO_MERGE, + FEAT_OMAP3_DSI_FIFO_BUG, +}; + +static const enum dispc_feature_id am43xx_dispc_features_list[] = { + FEAT_LCDENABLEPOL, + FEAT_LCDENABLESIGNAL, + FEAT_PCKFREEENABLE, + FEAT_FUNCGATED, + FEAT_LINEBUFFERSPLIT, + FEAT_ROWREPEATENABLE, + FEAT_RESIZECONF, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FIXED_ZORDER, + FEAT_FIFO_MERGE, +}; + +static const enum dispc_feature_id omap4_dispc_features_list[] = { + FEAT_MGR_LCD2, + FEAT_CORE_CLK_DIV, + FEAT_HANDLE_UV_SEPARATE, + FEAT_ATTR2, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FREE_ZORDER, + FEAT_FIFO_MERGE, + FEAT_BURST_2D, +}; + +static const enum dispc_feature_id omap5_dispc_features_list[] = { + FEAT_MGR_LCD2, + FEAT_MGR_LCD3, + FEAT_CORE_CLK_DIV, + FEAT_HANDLE_UV_SEPARATE, + FEAT_ATTR2, + FEAT_CPR, + FEAT_PRELOAD, + FEAT_FIR_COEF_V, + FEAT_ALPHA_FREE_ZORDER, + FEAT_FIFO_MERGE, + FEAT_BURST_2D, + FEAT_MFLAG, +}; + +static const struct dss_reg_field omap2_dispc_reg_fields[] = { + [FEAT_REG_FIRHINC] = { 11, 0 }, + [FEAT_REG_FIRVINC] = { 27, 16 }, + [FEAT_REG_FIFOLOWTHRESHOLD] = { 8, 0 }, + [FEAT_REG_FIFOHIGHTHRESHOLD] = { 24, 16 }, + [FEAT_REG_FIFOSIZE] = { 8, 0 }, + [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, + [FEAT_REG_VERTICALACCU] = { 25, 16 }, +}; + +static const struct dss_reg_field omap3_dispc_reg_fields[] = { + [FEAT_REG_FIRHINC] = { 12, 0 }, + [FEAT_REG_FIRVINC] = { 28, 16 }, + [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 }, + [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 }, + [FEAT_REG_FIFOSIZE] = { 10, 0 }, + [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, + [FEAT_REG_VERTICALACCU] = { 25, 16 }, +}; + +static const struct dss_reg_field omap4_dispc_reg_fields[] = { + [FEAT_REG_FIRHINC] = { 12, 0 }, + [FEAT_REG_FIRVINC] = { 28, 16 }, + [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 }, + [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 }, + [FEAT_REG_FIFOSIZE] = { 15, 0 }, + [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, + [FEAT_REG_VERTICALACCU] = { 26, 16 }, +}; + +static const enum omap_overlay_caps omap2_dispc_overlay_caps[] = { + /* OMAP_DSS_GFX */ + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO1 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO2 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, +}; + +static const enum omap_overlay_caps omap3430_dispc_overlay_caps[] = { + /* OMAP_DSS_GFX */ + OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO1 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO2 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, +}; + +static const enum omap_overlay_caps omap3630_dispc_overlay_caps[] = { + /* OMAP_DSS_GFX */ + OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO1 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO2 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, +}; + +static const enum omap_overlay_caps omap4_dispc_overlay_caps[] = { + /* OMAP_DSS_GFX */ + OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | + OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO1 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER | + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO2 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER | + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, + + /* OMAP_DSS_VIDEO3 */ + OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER | + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, +}; + +#define COLOR_ARRAY(arr...) (const u32[]) { arr, 0 } + +static const u32 *omap2_dispc_supported_color_modes[] = { + + /* OMAP_DSS_GFX */ + COLOR_ARRAY( + DRM_FORMAT_RGBX4444, DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB888), + + /* OMAP_DSS_VIDEO1 */ + COLOR_ARRAY( + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_YUYV, + DRM_FORMAT_UYVY), + + /* OMAP_DSS_VIDEO2 */ + COLOR_ARRAY( + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_YUYV, + DRM_FORMAT_UYVY), +}; + +static const u32 *omap3_dispc_supported_color_modes[] = { + /* OMAP_DSS_GFX */ + COLOR_ARRAY( + DRM_FORMAT_RGBX4444, DRM_FORMAT_ARGB4444, + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGBA8888, DRM_FORMAT_RGBX8888), + + /* OMAP_DSS_VIDEO1 */ + COLOR_ARRAY( + DRM_FORMAT_XRGB8888, DRM_FORMAT_RGB888, + DRM_FORMAT_RGBX4444, DRM_FORMAT_RGB565, + DRM_FORMAT_YUYV, DRM_FORMAT_UYVY), + + /* OMAP_DSS_VIDEO2 */ + COLOR_ARRAY( + DRM_FORMAT_RGBX4444, DRM_FORMAT_ARGB4444, + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_YUYV, + DRM_FORMAT_UYVY, DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGBA8888, DRM_FORMAT_RGBX8888), +}; + +static const u32 *omap4_dispc_supported_color_modes[] = { + /* OMAP_DSS_GFX */ + COLOR_ARRAY( + DRM_FORMAT_RGBX4444, DRM_FORMAT_ARGB4444, + DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGBA8888, DRM_FORMAT_RGBX8888, + DRM_FORMAT_ARGB1555, DRM_FORMAT_XRGB4444, + DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB1555), + + /* OMAP_DSS_VIDEO1 */ + COLOR_ARRAY( + DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444, + DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555, + DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12, + DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_UYVY, + DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555, + DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444, + DRM_FORMAT_RGBX8888), + + /* OMAP_DSS_VIDEO2 */ + COLOR_ARRAY( + DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444, + DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555, + DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12, + DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_UYVY, + DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555, + DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444, + DRM_FORMAT_RGBX8888), + + /* OMAP_DSS_VIDEO3 */ + COLOR_ARRAY( + DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444, + DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555, + DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12, + DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_UYVY, + DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555, + DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444, + DRM_FORMAT_RGBX8888), + + /* OMAP_DSS_WB */ + COLOR_ARRAY( + DRM_FORMAT_RGB565, DRM_FORMAT_RGBX4444, + DRM_FORMAT_YUYV, DRM_FORMAT_ARGB1555, + DRM_FORMAT_RGBA8888, DRM_FORMAT_NV12, + DRM_FORMAT_RGBA4444, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, DRM_FORMAT_UYVY, + DRM_FORMAT_ARGB4444, DRM_FORMAT_XRGB1555, + DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB4444, + DRM_FORMAT_RGBX8888), +}; + static const struct dispc_features omap24xx_dispc_feats = { .sw_start = 5, .fp_start = 15, @@ -3998,9 +4046,26 @@ static const struct dispc_features omap24xx_dispc_feats = { .mgr_width_max = 2048, .mgr_height_max = 2048, .max_lcd_pclk = 66500000, + .max_downscale = 2, + /* + * Assume the line width buffer to be 768 pixels as OMAP2 DISPC scaler + * cannot scale an image width larger than 768. + */ + .max_line_width = 768, + .min_pcd = 2, .calc_scaling = dispc_ovl_calc_scaling_24xx, .calc_core_clk = calc_core_clk_24xx, .num_fifos = 3, + .features = omap2_dispc_features_list, + .num_features = ARRAY_SIZE(omap2_dispc_features_list), + .reg_fields = omap2_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap2_dispc_reg_fields), + .overlay_caps = omap2_dispc_overlay_caps, + .supported_color_modes = omap2_dispc_supported_color_modes, + .num_mgrs = 2, + .num_ovls = 3, + .buffer_size_unit = 1, + .burst_size_unit = 8, .no_framedone_tv = true, .set_max_preload = false, .last_pixel_inc_missing = true, @@ -4019,9 +4084,22 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats = { .mgr_height_max = 2048, .max_lcd_pclk = 173000000, .max_tv_pclk = 59000000, + .max_downscale = 4, + .max_line_width = 1024, + .min_pcd = 1, .calc_scaling = dispc_ovl_calc_scaling_34xx, .calc_core_clk = calc_core_clk_34xx, .num_fifos = 3, + .features = omap3_dispc_features_list, + .num_features = ARRAY_SIZE(omap3_dispc_features_list), + .reg_fields = omap3_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields), + .overlay_caps = omap3430_dispc_overlay_caps, + .supported_color_modes = omap3_dispc_supported_color_modes, + .num_mgrs = 2, + .num_ovls = 3, + .buffer_size_unit = 1, + .burst_size_unit = 8, .no_framedone_tv = true, .set_max_preload = false, .last_pixel_inc_missing = true, @@ -4040,9 +4118,90 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats = { .mgr_height_max = 2048, .max_lcd_pclk = 173000000, .max_tv_pclk = 59000000, + .max_downscale = 4, + .max_line_width = 1024, + .min_pcd = 1, .calc_scaling = dispc_ovl_calc_scaling_34xx, .calc_core_clk = calc_core_clk_34xx, .num_fifos = 3, + .features = omap3_dispc_features_list, + .num_features = ARRAY_SIZE(omap3_dispc_features_list), + .reg_fields = omap3_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields), + .overlay_caps = omap3430_dispc_overlay_caps, + .supported_color_modes = omap3_dispc_supported_color_modes, + .num_mgrs = 2, + .num_ovls = 3, + .buffer_size_unit = 1, + .burst_size_unit = 8, + .no_framedone_tv = true, + .set_max_preload = false, + .last_pixel_inc_missing = true, +}; + +static const struct dispc_features omap36xx_dispc_feats = { + .sw_start = 7, + .fp_start = 19, + .bp_start = 31, + .sw_max = 256, + .vp_max = 4095, + .hp_max = 4096, + .mgr_width_start = 10, + .mgr_height_start = 26, + .mgr_width_max = 2048, + .mgr_height_max = 2048, + .max_lcd_pclk = 173000000, + .max_tv_pclk = 59000000, + .max_downscale = 4, + .max_line_width = 1024, + .min_pcd = 1, + .calc_scaling = dispc_ovl_calc_scaling_34xx, + .calc_core_clk = calc_core_clk_34xx, + .num_fifos = 3, + .features = omap3_dispc_features_list, + .num_features = ARRAY_SIZE(omap3_dispc_features_list), + .reg_fields = omap3_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields), + .overlay_caps = omap3630_dispc_overlay_caps, + .supported_color_modes = omap3_dispc_supported_color_modes, + .num_mgrs = 2, + .num_ovls = 3, + .buffer_size_unit = 1, + .burst_size_unit = 8, + .no_framedone_tv = true, + .set_max_preload = false, + .last_pixel_inc_missing = true, +}; + +static const struct dispc_features am43xx_dispc_feats = { + .sw_start = 7, + .fp_start = 19, + .bp_start = 31, + .sw_max = 256, + .vp_max = 4095, + .hp_max = 4096, + .mgr_width_start = 10, + .mgr_height_start = 26, + .mgr_width_max = 2048, + .mgr_height_max = 2048, + .max_lcd_pclk = 173000000, + .max_tv_pclk = 59000000, + .max_downscale = 4, + .max_line_width = 1024, + .min_pcd = 1, + .calc_scaling = dispc_ovl_calc_scaling_34xx, + .calc_core_clk = calc_core_clk_34xx, + .num_fifos = 3, + .features = am43xx_dispc_features_list, + .num_features = ARRAY_SIZE(am43xx_dispc_features_list), + .reg_fields = omap3_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap3_dispc_reg_fields), + .overlay_caps = omap3430_dispc_overlay_caps, + .supported_color_modes = omap3_dispc_supported_color_modes, + .num_mgrs = 1, + .num_ovls = 3, + .buffer_size_unit = 1, + .burst_size_unit = 8, .no_framedone_tv = true, .set_max_preload = false, .last_pixel_inc_missing = true, @@ -4061,9 +4220,22 @@ static const struct dispc_features omap44xx_dispc_feats = { .mgr_height_max = 2048, .max_lcd_pclk = 170000000, .max_tv_pclk = 185625000, + .max_downscale = 4, + .max_line_width = 2048, + .min_pcd = 1, .calc_scaling = dispc_ovl_calc_scaling_44xx, .calc_core_clk = calc_core_clk_44xx, .num_fifos = 5, + .features = omap4_dispc_features_list, + .num_features = ARRAY_SIZE(omap4_dispc_features_list), + .reg_fields = omap4_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap4_dispc_reg_fields), + .overlay_caps = omap4_dispc_overlay_caps, + .supported_color_modes = omap4_dispc_supported_color_modes, + .num_mgrs = 3, + .num_ovls = 4, + .buffer_size_unit = 16, + .burst_size_unit = 16, .gfx_fifo_workaround = true, .set_max_preload = true, .supports_sync_align = true, @@ -4087,9 +4259,22 @@ static const struct dispc_features omap54xx_dispc_feats = { .mgr_height_max = 4096, .max_lcd_pclk = 170000000, .max_tv_pclk = 186000000, + .max_downscale = 4, + .max_line_width = 2048, + .min_pcd = 1, .calc_scaling = dispc_ovl_calc_scaling_44xx, .calc_core_clk = calc_core_clk_44xx, .num_fifos = 5, + .features = omap5_dispc_features_list, + .num_features = ARRAY_SIZE(omap5_dispc_features_list), + .reg_fields = omap4_dispc_reg_fields, + .num_reg_fields = ARRAY_SIZE(omap4_dispc_reg_fields), + .overlay_caps = omap4_dispc_overlay_caps, + .supported_color_modes = omap4_dispc_supported_color_modes, + .num_mgrs = 4, + .num_ovls = 4, + .buffer_size_unit = 16, + .burst_size_unit = 16, .gfx_fifo_workaround = true, .mstandby_workaround = true, .set_max_preload = true, @@ -4101,54 +4286,6 @@ static const struct dispc_features omap54xx_dispc_feats = { .has_gamma_i734_bug = true, }; -static int dispc_init_features(struct platform_device *pdev) -{ - const struct dispc_features *src; - struct dispc_features *dst; - - dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL); - if (!dst) { - dev_err(&pdev->dev, "Failed to allocate DISPC Features\n"); - return -ENOMEM; - } - - switch (omapdss_get_version()) { - case OMAPDSS_VER_OMAP24xx: - src = &omap24xx_dispc_feats; - break; - - case OMAPDSS_VER_OMAP34xx_ES1: - src = &omap34xx_rev1_0_dispc_feats; - break; - - case OMAPDSS_VER_OMAP34xx_ES3: - case OMAPDSS_VER_OMAP3630: - case OMAPDSS_VER_AM35xx: - case OMAPDSS_VER_AM43xx: - src = &omap34xx_rev3_0_dispc_feats; - break; - - case OMAPDSS_VER_OMAP4430_ES1: - case OMAPDSS_VER_OMAP4430_ES2: - case OMAPDSS_VER_OMAP4: - src = &omap44xx_dispc_feats; - break; - - case OMAPDSS_VER_OMAP5: - case OMAPDSS_VER_DRA7xx: - src = &omap54xx_dispc_feats; - break; - - default: - return -ENODEV; - } - - memcpy(dst, src, sizeof(*dst)); - dispc.feat = dst; - - return 0; -} - static irqreturn_t dispc_irq_handler(int irq, void *arg) { if (!dispc.is_enabled) @@ -4225,10 +4362,9 @@ static const struct dispc_errata_i734_data { .ovli = { .screen_width = 1, .width = 1, .height = 1, - .color_mode = OMAP_DSS_COLOR_RGB24U, - .rotation = OMAP_DSS_ROT_0, - .rotation_type = OMAP_DSS_ROT_DMA, - .mirror = 0, + .fourcc = DRM_FORMAT_XRGB8888, + .rotation = DRM_MODE_ROTATE_0, + .rotation_type = OMAP_DSS_ROT_NONE, .pos_x = 0, .pos_y = 0, .out_width = 0, .out_height = 0, .global_alpha = 0xff, @@ -4266,7 +4402,7 @@ static int dispc_errata_i734_wa_init(void) return 0; i734_buf.size = i734.ovli.width * i734.ovli.height * - color_mode_to_bpp(i734.ovli.color_mode) / 8; + color_mode_to_bpp(i734.ovli.fourcc) / 8; i734_buf.vaddr = dma_alloc_writecombine(&dispc.pdev->dev, i734_buf.size, &i734_buf.paddr, GFP_KERNEL); @@ -4309,8 +4445,8 @@ static void dispc_errata_i734_wa(void) REG_FLD_MOD(DISPC_CONFIG, 0x1f, 8, 4); /* Setup and enable GFX plane */ - dispc_ovl_set_channel_out(OMAP_DSS_GFX, OMAP_DSS_CHANNEL_LCD); - dispc_ovl_setup(OMAP_DSS_GFX, &ovli, &i734.vm, false); + dispc_ovl_setup(OMAP_DSS_GFX, &ovli, &i734.vm, false, + OMAP_DSS_CHANNEL_LCD); dispc_ovl_enable(OMAP_DSS_GFX, true); /* Set up and enable display manager for LCD1 */ @@ -4350,7 +4486,6 @@ static void dispc_errata_i734_wa(void) static const struct dispc_ops dispc_ops = { .read_irqstatus = dispc_read_irqstatus, .clear_irqstatus = dispc_clear_irqstatus, - .read_irqenable = dispc_read_irqenable, .write_irqenable = dispc_write_irqenable, .request_irq = dispc_request_irq, @@ -4377,16 +4512,33 @@ static const struct dispc_ops dispc_ops = { .mgr_set_gamma = dispc_mgr_set_gamma, .ovl_enable = dispc_ovl_enable, - .ovl_enabled = dispc_ovl_enabled, - .ovl_set_channel_out = dispc_ovl_set_channel_out, .ovl_setup = dispc_ovl_setup, .ovl_get_color_modes = dispc_ovl_get_color_modes, }; /* DISPC HW IP initialisation */ +static const struct of_device_id dispc_of_match[] = { + { .compatible = "ti,omap2-dispc", .data = &omap24xx_dispc_feats }, + { .compatible = "ti,omap3-dispc", .data = &omap36xx_dispc_feats }, + { .compatible = "ti,omap4-dispc", .data = &omap44xx_dispc_feats }, + { .compatible = "ti,omap5-dispc", .data = &omap54xx_dispc_feats }, + { .compatible = "ti,dra7-dispc", .data = &omap54xx_dispc_feats }, + {}, +}; + +static const struct soc_device_attribute dispc_soc_devices[] = { + { .machine = "OMAP3[45]*", + .revision = "ES[12].?", .data = &omap34xx_rev1_0_dispc_feats }, + { .machine = "OMAP3[45]*", .data = &omap34xx_rev3_0_dispc_feats }, + { .machine = "AM35*", .data = &omap34xx_rev3_0_dispc_feats }, + { .machine = "AM43*", .data = &am43xx_dispc_feats }, + { /* sentinel */ } +}; + static int dispc_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); + const struct soc_device_attribute *soc; u32 rev; int r = 0; struct resource *dispc_mem; @@ -4396,26 +4548,24 @@ static int dispc_bind(struct device *dev, struct device *master, void *data) spin_lock_init(&dispc.control_lock); - r = dispc_init_features(dispc.pdev); - if (r) - return r; + /* + * The OMAP3-based models can't be told apart using the compatible + * string, use SoC device matching. + */ + soc = soc_device_match(dispc_soc_devices); + if (soc) + dispc.feat = soc->data; + else + dispc.feat = of_match_device(dispc_of_match, &pdev->dev)->data; r = dispc_errata_i734_wa_init(); if (r) return r; dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); - if (!dispc_mem) { - DSSERR("can't get IORESOURCE_MEM DISPC\n"); - return -EINVAL; - } - - dispc.base = devm_ioremap(&pdev->dev, dispc_mem->start, - resource_size(dispc_mem)); - if (!dispc.base) { - DSSERR("can't ioremap DISPC\n"); - return -ENOMEM; - } + dispc.base = devm_ioremap_resource(&pdev->dev, dispc_mem); + if (IS_ERR(dispc.base)) + return PTR_ERR(dispc.base); dispc.irq = platform_get_irq(dispc.pdev, 0); if (dispc.irq < 0) { @@ -4535,15 +4685,6 @@ static const struct dev_pm_ops dispc_pm_ops = { .runtime_resume = dispc_runtime_resume, }; -static const struct of_device_id dispc_of_match[] = { - { .compatible = "ti,omap2-dispc", }, - { .compatible = "ti,omap3-dispc", }, - { .compatible = "ti,omap4-dispc", }, - { .compatible = "ti,omap5-dispc", }, - { .compatible = "ti,dra7-dispc", }, - {}, -}; - static struct platform_driver omap_dispchw_driver = { .probe = dispc_probe, .remove = dispc_remove, |