diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-09-26 16:48:55 +0300 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-09-26 16:48:55 +0300 |
commit | 69036f0ccd9d48b4e999be4e98fa459430ec93b4 (patch) | |
tree | e09e075957c7e9b8299e57883d50eb3cff6ee3b2 | |
parent | 866f0956cba7d28432f20f8a696e5c1a2b40b915 (diff) | |
parent | 6e5264b0380593efda8157406ec40f00daac9f2d (diff) |
Merge branch 'archit/wb-dispc-for-3.7'
Merge omapdss writeback work. These patches implement the low level writeback
features in the DISPC, but do not yet add a way to actually use the writeback
from the userspace.
* archit/wb-dispc-for-3.7:
OMAPDSS: DISPC: Configure color conversion coefficients for writeback
OMAPDSS: DISPC: Add manager like functions for writeback
OMAPDSS: DISPC: Configure writeback FIFOs
OMAPDSS: DISPC: Configure writeback specific parameters in dispc_wb_setup()
OMAPDSS: DISPC: Configure overlay-like parameters in dispc_wb_setup
OMAPDSS: DISPC: Add function to set channel in for writeback
OMAPDSS: DISPC: Don't set chroma resampling bit for writeback
OMAPDSS: DISPC: Downscale chroma if plane is writeback
OMAPDSS: DISPC: Configure input and output sizes for writeback
OMAPDSS: DISPC: Add writeback register offsets and dss features structs
OMAPDSS: DISPC: Allow both upscaling and downscaling of chroma
OMAPDSS: DIPSC: Relax scaling limitations when in memory to memory mode
OMAPDSS: DISPC: Don't pass channel out when configuring overlays
OMAPDSS: DISPC: Make dispc_ovl_setup call dispc_ovl_setup_common
OMAPDSS: OVERLAY: Add position and replication as overlay caps
OMAPDSS: DISPC: Pass overlay caps as a parameter to dispc plane functions
OMAPDSS: DISPC: Simplify function names for setting pipeline input and output sizes
OMAPDSS: DISPC: Constify omap_overlay_info in dispc_ovl_setup()
-rw-r--r-- | drivers/video/omap2/dss/apply.c | 2 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dispc.c | 562 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dispc.h | 33 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss.h | 25 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss_features.c | 57 | ||||
-rw-r--r-- | drivers/video/omap2/dss/dss_features.h | 1 | ||||
-rw-r--r-- | include/video/omapdss.h | 15 |
7 files changed, 510 insertions, 185 deletions
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index 2b1fa851a8b..19d66f471b4 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -584,7 +584,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl) replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode); - r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings); + r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false); if (r) { /* * We can't do much here, as this function can be called from diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 811fe381aae..a173a9481a2 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -86,14 +86,15 @@ struct dispc_features { u16 sw_max; u16 vp_max; u16 hp_max; - int (*calc_scaling) (enum omap_channel channel, + int (*calc_scaling) (enum omap_plane plane, const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, - u16 pos_x, unsigned long *core_clk); - unsigned long (*calc_core_clk) (enum omap_channel channel, - u16 width, u16 height, u16 out_width, u16 out_height); + u16 pos_x, unsigned long *core_clk, bool mem_to_mem); + unsigned long (*calc_core_clk) (enum omap_plane plane, + u16 width, u16 height, u16 out_width, u16 out_height, + bool mem_to_mem); u8 num_fifos; /* swap GFX & WB fifos */ @@ -235,7 +236,14 @@ static const struct { }, }; +struct color_conv_coef { + int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; + int full_range; +}; + static void _omap_dispc_set_irqs(void); +static unsigned long dispc_plane_pclk_rate(enum omap_plane plane); +static unsigned long dispc_plane_lclk_rate(enum omap_plane plane); static inline void dispc_write_reg(const u16 idx, u32 val) { @@ -533,6 +541,11 @@ u32 dispc_mgr_get_framedone_irq(enum omap_channel channel) return mgr_desc[channel].framedone_irq; } +u32 dispc_wb_get_framedone_irq(void) +{ + return DISPC_IRQ_FRAMEDONEWB; +} + bool dispc_mgr_go_busy(enum omap_channel channel) { return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; @@ -560,6 +573,30 @@ void dispc_mgr_go(enum omap_channel channel) mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1); } +bool dispc_wb_go_busy(void) +{ + return REG_GET(DISPC_CONTROL2, 6, 6) == 1; +} + +void dispc_wb_go(void) +{ + enum omap_plane plane = OMAP_DSS_WB; + bool enable, go; + + enable = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1; + + if (!enable) + return; + + go = REG_GET(DISPC_CONTROL2, 6, 6) == 1; + if (go) { + DSSERR("GO bit not down for WB\n"); + return; + } + + REG_FLD_MOD(DISPC_CONTROL2, 1, 6, 6); +} + static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value) { dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); @@ -642,41 +679,41 @@ static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc, } } -static void _dispc_setup_color_conv_coef(void) -{ - int i; - const struct color_conv_coef { - int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; - int full_range; - } ctbl_bt601_5 = { - 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, - }; - - const struct color_conv_coef *ct; +static void dispc_ovl_write_color_conv_coef(enum omap_plane plane, + const struct color_conv_coef *ct) +{ #define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) - ct = &ctbl_bt601_5; + dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry)); + dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy, ct->rcb)); + dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr)); + dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by)); + dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb)); - for (i = 1; i < dss_feat_get_num_ovls(); i++) { - dispc_write_reg(DISPC_OVL_CONV_COEF(i, 0), - CVAL(ct->rcr, ct->ry)); - dispc_write_reg(DISPC_OVL_CONV_COEF(i, 1), - CVAL(ct->gy, ct->rcb)); - dispc_write_reg(DISPC_OVL_CONV_COEF(i, 2), - CVAL(ct->gcb, ct->gcr)); - dispc_write_reg(DISPC_OVL_CONV_COEF(i, 3), - CVAL(ct->bcr, ct->by)); - dispc_write_reg(DISPC_OVL_CONV_COEF(i, 4), - CVAL(0, ct->bcb)); - - REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), ct->full_range, - 11, 11); - } + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11); #undef CVAL } +static void dispc_setup_color_conv_coef(void) +{ + int i; + int num_ovl = dss_feat_get_num_ovls(); + int num_wb = dss_feat_get_num_wbs(); + const struct color_conv_coef ctbl_bt601_5_ovl = { + 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, + }; + const struct color_conv_coef ctbl_bt601_5_wb = { + 66, 112, -38, 129, -94, -74, 25, -18, 112, 0, + }; + + for (i = 1; i < num_ovl; i++) + dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_ovl); + + for (; i < num_wb; i++) + dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_wb); +} static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr) { @@ -698,24 +735,32 @@ static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr) dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); } -static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y) +static void dispc_ovl_set_pos(enum omap_plane plane, + enum omap_overlay_caps caps, int x, int y) { - u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); + u32 val; + + if ((caps & OMAP_DSS_OVL_CAP_POS) == 0) + return; + + val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); dispc_write_reg(DISPC_OVL_POSITION(plane), val); } -static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height) +static void dispc_ovl_set_input_size(enum omap_plane plane, int width, + int height) { u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); - if (plane == OMAP_DSS_GFX) + if (plane == OMAP_DSS_GFX || plane == OMAP_DSS_WB) dispc_write_reg(DISPC_OVL_SIZE(plane), val); else dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); } -static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height) +static void dispc_ovl_set_output_size(enum omap_plane plane, int width, + int height) { u32 val; @@ -723,14 +768,16 @@ static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height) val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); - dispc_write_reg(DISPC_OVL_SIZE(plane), val); + if (plane == OMAP_DSS_WB) + dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); + else + dispc_write_reg(DISPC_OVL_SIZE(plane), val); } -static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder) +static void dispc_ovl_set_zorder(enum omap_plane plane, + enum omap_overlay_caps caps, u8 zorder) { - struct omap_overlay *ovl = omap_dss_get_overlay(plane); - - if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) + if ((caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) return; REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26); @@ -747,23 +794,22 @@ static void dispc_ovl_enable_zorder_planes(void) REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); } -static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable) +static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, + enum omap_overlay_caps caps, bool enable) { - struct omap_overlay *ovl = omap_dss_get_overlay(plane); - - if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0) + if ((caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0) return; REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); } -static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha) +static void dispc_ovl_setup_global_alpha(enum omap_plane plane, + enum omap_overlay_caps caps, u8 global_alpha) { static const unsigned shifts[] = { 0, 8, 16, 24, }; int shift; - struct omap_overlay *ovl = omap_dss_get_overlay(plane); - if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) + if ((caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) return; shift = shifts[plane]; @@ -971,10 +1017,17 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) return channel; } +void dispc_wb_set_channel_in(enum dss_writeback_channel channel) +{ + enum omap_plane plane = OMAP_DSS_WB; + + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), channel, 18, 16); +} + static void dispc_ovl_set_burst_size(enum omap_plane plane, enum omap_burst_size burst_size) { - static const unsigned shifts[] = { 6, 14, 14, 14, }; + static const unsigned shifts[] = { 6, 14, 14, 14, 14, }; int shift; shift = shifts[plane]; @@ -1051,11 +1104,15 @@ static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable) dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); } -static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable) +static void dispc_ovl_enable_replication(enum omap_plane plane, + enum omap_overlay_caps caps, bool enable) { static const unsigned shifts[] = { 5, 10, 10, 10 }; int shift; + if ((caps & OMAP_DSS_OVL_CAP_REPLICATION) == 0) + return; + shift = shifts[plane]; REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift); } @@ -1202,6 +1259,14 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, if (manual_update && dss_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) { + /* + * Most optimal configuration for writeback is to push out data + * to the interconnect the moment writeback pushes enough pixels + * in the FIFO to form a burst + */ + *fifo_low = 0; + *fifo_high = burst_size; } else { *fifo_low = ovl_fifo_size - burst_size; *fifo_high = total_fifo_size - buf_unit; @@ -1444,6 +1509,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane, { int scale_x = out_width != orig_width; int scale_y = out_height != orig_height; + bool chroma_upscale = plane != OMAP_DSS_WB ? true : false; if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) return; @@ -1451,7 +1517,8 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane, color_mode != OMAP_DSS_COLOR_UYVY && color_mode != OMAP_DSS_COLOR_NV12)) { /* reset chroma resampling for RGB formats */ - REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); + if (plane != OMAP_DSS_WB) + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); return; } @@ -1460,23 +1527,34 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane, switch (color_mode) { case OMAP_DSS_COLOR_NV12: - /* UV is subsampled by 2 vertically*/ - orig_height >>= 1; - /* UV is subsampled by 2 horz.*/ - orig_width >>= 1; + if (chroma_upscale) { + /* UV is subsampled by 2 horizontally and vertically */ + orig_height >>= 1; + orig_width >>= 1; + } else { + /* UV is downsampled by 2 horizontally and vertically */ + orig_height <<= 1; + orig_width <<= 1; + } + break; case OMAP_DSS_COLOR_YUV2: case OMAP_DSS_COLOR_UYVY: - /*For YUV422 with 90/270 rotation, - *we don't upsample chroma - */ + /* For YUV422 with 90/270 rotation, we don't upsample chroma */ if (rotation == OMAP_DSS_ROT_0 || - rotation == OMAP_DSS_ROT_180) - /* UV is subsampled by 2 hrz*/ - orig_width >>= 1; + rotation == OMAP_DSS_ROT_180) { + if (chroma_upscale) + /* UV is subsampled by 2 horizontally */ + orig_width >>= 1; + else + /* UV is downsampled by 2 horizontally */ + orig_width <<= 1; + } + /* must use FIR for YUV422 if rotated */ if (rotation != OMAP_DSS_ROT_0) scale_x = scale_y = true; + break; default: BUG(); @@ -1492,8 +1570,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane, out_width, out_height, five_taps, rotation, DISPC_COLOR_COMPONENT_UV); - REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), - (scale_x || scale_y) ? 1 : 0, 8, 8); + if (plane != OMAP_DSS_WB) + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), + (scale_x || scale_y) ? 1 : 0, 8, 8); + /* set H scaling */ REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5); /* set V scaling */ @@ -1909,22 +1989,19 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width, * This function is used to avoid synclosts in OMAP3, because of some * undocumented horizontal position and timing related limitations. */ -static int check_horiz_timing_omap3(enum omap_channel channel, +static int check_horiz_timing_omap3(enum omap_plane plane, const struct omap_video_timings *t, u16 pos_x, u16 width, u16 height, u16 out_width, u16 out_height) { int DS = DIV_ROUND_UP(height, out_height); - unsigned long nonactive, lclk, pclk; + unsigned long nonactive; static const u8 limits[3] = { 8, 10, 20 }; u64 val, blank; + unsigned long pclk = dispc_plane_pclk_rate(plane); + unsigned long lclk = dispc_plane_lclk_rate(plane); int i; nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; - pclk = dispc_mgr_pclk_rate(channel); - if (dss_mgr_is_lcd(channel)) - lclk = dispc_mgr_lclk_rate(channel); - else - lclk = dispc_fclk_rate(); i = 0; if (out_height < height) @@ -1961,13 +2038,14 @@ static int check_horiz_timing_omap3(enum omap_channel channel, return 0; } -static unsigned long calc_core_clk_five_taps(enum omap_channel channel, +static unsigned long calc_core_clk_five_taps(enum omap_plane plane, const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode) { u32 core_clk = 0; - u64 tmp, pclk = dispc_mgr_pclk_rate(channel); + u64 tmp; + unsigned long pclk = dispc_plane_pclk_rate(plane); if (height <= out_height && width <= out_width) return (unsigned long) pclk; @@ -2001,10 +2079,10 @@ static unsigned long calc_core_clk_five_taps(enum omap_channel channel, return core_clk; } -static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width, - u16 height, u16 out_width, u16 out_height) +static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width, + u16 height, u16 out_width, u16 out_height, bool mem_to_mem) { - unsigned long pclk = dispc_mgr_pclk_rate(channel); + unsigned long pclk = dispc_plane_pclk_rate(plane); if (height > out_height && width > out_width) return pclk * 4; @@ -2012,11 +2090,11 @@ static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width, return pclk * 2; } -static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width, - u16 height, u16 out_width, u16 out_height) +static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width, + u16 height, u16 out_width, u16 out_height, bool mem_to_mem) { unsigned int hf, vf; - unsigned long pclk = dispc_mgr_pclk_rate(channel); + unsigned long pclk = dispc_plane_pclk_rate(plane); /* * FIXME how to determine the 'A' factor @@ -2039,10 +2117,21 @@ static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width, return pclk * vf * hf; } -static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width, - u16 height, u16 out_width, u16 out_height) +static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width, + u16 height, u16 out_width, u16 out_height, bool mem_to_mem) { - unsigned long pclk = dispc_mgr_pclk_rate(channel); + unsigned long pclk; + + /* + * If the overlay/writeback is in mem to mem mode, there are no + * downscaling limitations with respect to pixel clock, return 1 as + * required core clock to represent that we have sufficient enough + * core clock to do maximum downscaling + */ + if (mem_to_mem) + return 1; + + pclk = dispc_plane_pclk_rate(plane); if (width > out_width) return DIV_ROUND_UP(pclk, out_width) * width; @@ -2050,25 +2139,26 @@ static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width, return pclk; } -static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel, +static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane, const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, - u16 pos_x, unsigned long *core_clk) + 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); + *five_taps = false; do { in_height = DIV_ROUND_UP(height, *decim_y); in_width = DIV_ROUND_UP(width, *decim_x); - *core_clk = dispc.feat->calc_core_clk(channel, in_width, - in_height, out_width, out_height); + *core_clk = dispc.feat->calc_core_clk(plane, in_width, + in_height, out_width, out_height, mem_to_mem); error = (in_width > maxsinglelinewidth || !*core_clk || *core_clk > dispc_core_clk_rate()); if (error) { @@ -2090,12 +2180,12 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel, return 0; } -static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel, +static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane, const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, - u16 pos_x, unsigned long *core_clk) + u16 pos_x, unsigned long *core_clk, bool mem_to_mem) { int error; u16 in_width, in_height; @@ -2106,19 +2196,21 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel, do { in_height = DIV_ROUND_UP(height, *decim_y); in_width = DIV_ROUND_UP(width, *decim_x); - *core_clk = calc_core_clk_five_taps(channel, mgr_timings, + *core_clk = calc_core_clk_five_taps(plane, mgr_timings, in_width, in_height, out_width, out_height, color_mode); - error = check_horiz_timing_omap3(channel, mgr_timings, pos_x, - in_width, in_height, out_width, out_height); + error = check_horiz_timing_omap3(plane, mgr_timings, + pos_x, in_width, in_height, out_width, + out_height); if (in_width > maxsinglelinewidth) if (in_height > out_height && in_height < out_height * 2) *five_taps = false; if (!*five_taps) - *core_clk = dispc.feat->calc_core_clk(channel, in_width, - in_height, out_width, out_height); + *core_clk = dispc.feat->calc_core_clk(plane, in_width, + in_height, out_width, out_height, + mem_to_mem); error = (error || in_width > maxsinglelinewidth * 2 || (in_width > maxsinglelinewidth && *five_taps) || @@ -2135,7 +2227,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel, } } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); - if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, height, + if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height, out_width, out_height)){ DSSERR("horizontal timing too tight\n"); return -EINVAL; @@ -2154,21 +2246,27 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel, return 0; } -static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel, +static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane, const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, - u16 pos_x, unsigned long *core_clk) + 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 = DIV_ROUND_UP(height, *decim_y); const int maxsinglelinewidth = dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); + unsigned long pclk = dispc_plane_pclk_rate(plane); + const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); + + if (mem_to_mem) + in_width_max = DIV_ROUND_UP(out_width, maxdownscale); + else + in_width_max = dispc_core_clk_rate() / + DIV_ROUND_UP(pclk, out_width); - in_width_max = dispc_core_clk_rate() / - DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), out_width); *decim_x = DIV_ROUND_UP(width, in_width_max); *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min; @@ -2185,20 +2283,19 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel, return -EINVAL; } - *core_clk = dispc.feat->calc_core_clk(channel, in_width, in_height, - out_width, out_height); + *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height, + out_width, out_height, mem_to_mem); return 0; } static int dispc_ovl_calc_scaling(enum omap_plane plane, - enum omap_channel channel, + enum omap_overlay_caps caps, const struct omap_video_timings *mgr_timings, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, bool *five_taps, int *x_predecim, int *y_predecim, u16 pos_x, - enum omap_dss_rotation_type rotation_type) + enum omap_dss_rotation_type rotation_type, bool mem_to_mem) { - struct omap_overlay *ovl = omap_dss_get_overlay(plane); const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); const int max_decim_limit = 16; unsigned long core_clk = 0; @@ -2207,7 +2304,7 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, if (width == out_width && height == out_height) return 0; - if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) + if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0) return -EINVAL; *x_predecim = max_decim_limit; @@ -2233,9 +2330,10 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, if (decim_y > *y_predecim || out_height > height * 8) return -EINVAL; - ret = dispc.feat->calc_scaling(channel, mgr_timings, width, height, - out_width, out_height, color_mode, five_taps, x_predecim, - y_predecim, &decim_x, &decim_y, pos_x, &core_clk); + ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height, + out_width, out_height, color_mode, five_taps, + x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk, + mem_to_mem); if (ret) return ret; @@ -2255,70 +2353,64 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, return 0; } -int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, - bool replication, const struct omap_video_timings *mgr_timings) +static int dispc_ovl_setup_common(enum omap_plane 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, + u8 global_alpha, enum omap_dss_rotation_type rotation_type, + bool replication, const struct omap_video_timings *mgr_timings, + bool mem_to_mem) { - struct omap_overlay *ovl = omap_dss_get_overlay(plane); bool five_taps = true; bool fieldmode = 0; int r, cconv = 0; unsigned offset0, offset1; s32 row_inc; s32 pix_inc; - u16 frame_height = oi->height; + u16 frame_height = height; unsigned int field_offset = 0; - u16 in_height = oi->height; - u16 in_width = oi->width; - u16 out_width, out_height; - enum omap_channel channel; + u16 in_height = height; + u16 in_width = width; int x_predecim = 1, y_predecim = 1; bool ilace = mgr_timings->interlace; - channel = dispc_ovl_get_channel_out(plane); - - DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> " - "%dx%d, cmode %x, rot %d, mir %d, ilace %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, ilace, channel, replication); - - if (oi->paddr == 0) + if (paddr == 0) return -EINVAL; - out_width = oi->out_width == 0 ? oi->width : oi->out_width; - out_height = oi->out_height == 0 ? oi->height : oi->out_height; + out_width = out_width == 0 ? width : out_width; + out_height = out_height == 0 ? height : out_height; - if (ilace && oi->height == out_height) + if (ilace && height == out_height) fieldmode = 1; if (ilace) { if (fieldmode) in_height /= 2; - oi->pos_y /= 2; + pos_y /= 2; out_height /= 2; DSSDBG("adjusting for ilace: height %d, pos_y %d, " - "out_height %d\n", - in_height, oi->pos_y, out_height); + "out_height %d\n", in_height, pos_y, + out_height); } - if (!dss_feat_color_mode_supported(plane, oi->color_mode)) + if (!dss_feat_color_mode_supported(plane, color_mode)) return -EINVAL; - r = dispc_ovl_calc_scaling(plane, channel, mgr_timings, in_width, - in_height, out_width, out_height, oi->color_mode, - &five_taps, &x_predecim, &y_predecim, oi->pos_x, - oi->rotation_type); + r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width, + in_height, out_width, out_height, color_mode, + &five_taps, &x_predecim, &y_predecim, pos_x, + rotation_type, mem_to_mem); if (r) return r; in_width = DIV_ROUND_UP(in_width, x_predecim); in_height = DIV_ROUND_UP(in_height, y_predecim); - if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || - oi->color_mode == OMAP_DSS_COLOR_UYVY || - oi->color_mode == OMAP_DSS_COLOR_NV12) + if (color_mode == OMAP_DSS_COLOR_YUV2 || + color_mode == OMAP_DSS_COLOR_UYVY || + color_mode == OMAP_DSS_COLOR_NV12) cconv = 1; if (ilace && !fieldmode) { @@ -2344,70 +2436,144 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, row_inc = 0; pix_inc = 0; - if (oi->rotation_type == OMAP_DSS_ROT_TILER) - calc_tiler_rotation_offset(oi->screen_width, in_width, - oi->color_mode, fieldmode, field_offset, + if (rotation_type == OMAP_DSS_ROT_TILER) + calc_tiler_rotation_offset(screen_width, in_width, + color_mode, fieldmode, field_offset, &offset0, &offset1, &row_inc, &pix_inc, x_predecim, y_predecim); - else if (oi->rotation_type == OMAP_DSS_ROT_DMA) - calc_dma_rotation_offset(oi->rotation, oi->mirror, - oi->screen_width, in_width, frame_height, - oi->color_mode, fieldmode, field_offset, + else if (rotation_type == OMAP_DSS_ROT_DMA) + calc_dma_rotation_offset(rotation, mirror, + screen_width, in_width, frame_height, + color_mode, fieldmode, field_offset, &offset0, &offset1, &row_inc, &pix_inc, x_predecim, y_predecim); else - calc_vrfb_rotation_offset(oi->rotation, oi->mirror, - oi->screen_width, in_width, frame_height, - oi->color_mode, fieldmode, field_offset, + calc_vrfb_rotation_offset(rotation, mirror, + screen_width, in_width, frame_height, + color_mode, fieldmode, field_offset, &offset0, &offset1, &row_inc, &pix_inc, x_predecim, y_predecim); DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", offset0, offset1, row_inc, pix_inc); - dispc_ovl_set_color_mode(plane, oi->color_mode); + dispc_ovl_set_color_mode(plane, color_mode); - dispc_ovl_configure_burst_type(plane, oi->rotation_type); + dispc_ovl_configure_burst_type(plane, rotation_type); - dispc_ovl_set_ba0(plane, oi->paddr + offset0); - dispc_ovl_set_ba1(plane, oi->paddr + offset1); + dispc_ovl_set_ba0(plane, paddr + offset0); + dispc_ovl_set_ba1(plane, paddr + offset1); - if (OMAP_DSS_COLOR_NV12 == oi->color_mode) { - dispc_ovl_set_ba0_uv(plane, oi->p_uv_addr + offset0); - dispc_ovl_set_ba1_uv(plane, oi->p_uv_addr + offset1); + if (OMAP_DSS_COLOR_NV12 == color_mode) { + dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0); + dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1); } - dispc_ovl_set_row_inc(plane, row_inc); dispc_ovl_set_pix_inc(plane, pix_inc); - DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width, + DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, in_width, in_height, out_width, out_height); - dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); + dispc_ovl_set_pos(plane, caps, pos_x, pos_y); - dispc_ovl_set_pic_size(plane, in_width, in_height); + dispc_ovl_set_input_size(plane, in_width, in_height); - if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { + if (caps & OMAP_DSS_OVL_CAP_SCALE) { dispc_ovl_set_scaling(plane, in_width, in_height, out_width, out_height, ilace, five_taps, fieldmode, - oi->color_mode, oi->rotation); - dispc_ovl_set_vid_size(plane, out_width, out_height); + color_mode, 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, oi->rotation, oi->mirror, - oi->color_mode); + dispc_ovl_set_rotation_attrs(plane, rotation, mirror, color_mode); - dispc_ovl_set_zorder(plane, oi->zorder); - dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha); - dispc_ovl_setup_global_alpha(plane, oi->global_alpha); + dispc_ovl_set_zorder(plane, caps, zorder); + dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha); + dispc_ovl_setup_global_alpha(plane, caps, global_alpha); - dispc_ovl_enable_replication(plane, replication); + dispc_ovl_enable_replication(plane, caps, replication); return 0; } +int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, + bool replication, const struct omap_video_timings *mgr_timings, + bool mem_to_mem) +{ + int r; + struct omap_overlay *ovl = omap_dss_get_overlay(plane); + enum omap_channel channel; + + channel = dispc_ovl_get_channel_out(plane); + + DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> " + "%dx%d, cmode %x, rot %d, mir %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); + + r = dispc_ovl_setup_common(plane, ovl->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->rotation_type, replication, mgr_timings, mem_to_mem); + + return r; +} + +int dispc_wb_setup(const struct omap_dss_writeback_info *wi, + bool mem_to_mem, const struct omap_video_timings *mgr_timings) +{ + int r; + u32 l; + enum omap_plane plane = OMAP_DSS_WB; + const int pos_x = 0, pos_y = 0; + const u8 zorder = 0, global_alpha = 0; + const bool replication = false; + bool truncation; + int in_width = mgr_timings->x_res; + int in_height = mgr_timings->y_res; + enum omap_overlay_caps caps = + 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); + + 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->pre_mult_alpha, global_alpha, wi->rotation_type, + replication, mgr_timings, 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: + truncation = true; + break; + default: + truncation = false; + break; + } + + /* setup extra DISPC_WB_ATTRIBUTES */ + l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); + l = FLD_MOD(l, truncation, 10, 10); /* TRUNCATIONENABLE */ + l = FLD_MOD(l, mem_to_mem, 19, 19); /* WRITEBACKMODE */ + dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l); + + return r; +} + int dispc_ovl_enable(enum omap_plane plane, bool enable) { DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); @@ -2560,6 +2726,47 @@ void dispc_mgr_enable(enum omap_channel channel, bool enable) BUG(); } +void dispc_wb_enable(bool enable) +{ + enum omap_plane plane = OMAP_DSS_WB; + struct completion frame_done_completion; + bool is_on; + int r; + u32 irq; + + is_on = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0); + irq = DISPC_IRQ_FRAMEDONEWB; + + if (!enable && is_on) { + init_completion(&frame_done_completion); + + r = omap_dispc_register_isr(dispc_disable_isr, + &frame_done_completion, irq); + if (r) + DSSERR("failed to register FRAMEDONEWB isr\n"); + } + + REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0); + + if (!enable && is_on) { + if (!wait_for_completion_timeout(&frame_done_completion, + msecs_to_jiffies(100))) + DSSERR("timeout waiting for FRAMEDONEWB\n"); + + r = omap_dispc_unregister_isr(dispc_disable_isr, + &frame_done_completion, irq); + if (r) + DSSERR("failed to unregister FRAMEDONEWB isr\n"); + } +} + +bool dispc_wb_is_enabled(void) +{ + enum omap_plane plane = OMAP_DSS_WB; + + return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0); +} + void dispc_lcd_enable_signal_polarity(bool act_high) { if (!dss_has_feature(FEAT_LCDENABLEPOL)) @@ -2963,6 +3170,23 @@ unsigned long dispc_core_clk_rate(void) return fclk / lcd; } +static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) +{ + enum omap_channel channel = dispc_ovl_get_channel_out(plane); + + return dispc_mgr_pclk_rate(channel); +} + +static unsigned long dispc_plane_lclk_rate(enum omap_plane plane) +{ + enum omap_channel channel = dispc_ovl_get_channel_out(plane); + + if (dss_mgr_is_lcd(channel)) + return dispc_mgr_lclk_rate(channel); + else + return dispc_fclk_rate(); + +} static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) { int lcd, pcd; @@ -3756,7 +3980,7 @@ static void _omap_dispc_initial_config(void) if (dss_has_feature(FEAT_FUNCGATED)) REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); - _dispc_setup_color_conv_coef(); + dispc_setup_color_conv_coef(); dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h index 42e56cc7cdb..222363c6e62 100644 --- a/drivers/video/omap2/dss/dispc.h +++ b/drivers/video/omap2/dss/dispc.h @@ -373,6 +373,7 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane) case OMAP_DSS_VIDEO2: return 0x0000; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x0008; default: BUG(); @@ -388,6 +389,7 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane) case OMAP_DSS_VIDEO2: return 0x0004; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x000C; default: BUG(); @@ -407,6 +409,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane) return 0x04BC; case OMAP_DSS_VIDEO3: return 0x0310; + case OMAP_DSS_WB: + return 0x0118; default: BUG(); return 0; @@ -425,6 +429,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane) return 0x04C0; case OMAP_DSS_VIDEO3: return 0x0314; + case OMAP_DSS_WB: + return 0x011C; default: BUG(); return 0; @@ -454,6 +460,7 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane) case OMAP_DSS_VIDEO2: return 0x000C; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x00A8; default: BUG(); @@ -470,6 +477,7 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane) case OMAP_DSS_VIDEO2: return 0x0010; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x0070; default: BUG(); @@ -489,6 +497,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane) return 0x04DC; case OMAP_DSS_VIDEO3: return 0x032C; + case OMAP_DSS_WB: + return 0x0310; default: BUG(); return 0; @@ -504,6 +514,7 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane) case OMAP_DSS_VIDEO2: return 0x0014; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x008C; default: BUG(); @@ -537,6 +548,7 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane) case OMAP_DSS_VIDEO2: return 0x001C; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x00A4; default: BUG(); @@ -553,6 +565,7 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane) case OMAP_DSS_VIDEO2: return 0x0020; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x0098; default: BUG(); @@ -602,6 +615,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane) case OMAP_DSS_VIDEO2: return 0x0024; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x0090; default: BUG(); @@ -621,6 +635,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane) return 0x055C; case OMAP_DSS_VIDEO3: return 0x0424; + case OMAP_DSS_WB: + return 0x290; default: BUG(); return 0; @@ -637,6 +653,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane) case OMAP_DSS_VIDEO2: return 0x0028; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x0094; default: BUG(); @@ -655,6 +672,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane) case OMAP_DSS_VIDEO2: return 0x002C; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x0000; default: BUG(); @@ -674,6 +692,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane) return 0x0560; case OMAP_DSS_VIDEO3: return 0x0428; + case OMAP_DSS_WB: + return 0x0294; default: BUG(); return 0; @@ -690,6 +710,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane) case OMAP_DSS_VIDEO2: return 0x0030; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x0004; default: BUG(); @@ -709,6 +730,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane) return 0x0564; case OMAP_DSS_VIDEO3: return 0x042C; + case OMAP_DSS_WB: + return 0x0298; default: BUG(); return 0; @@ -726,6 +749,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i) case OMAP_DSS_VIDEO2: return 0x0034 + i * 0x8; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x0010 + i * 0x8; default: BUG(); @@ -746,6 +770,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i) return 0x0568 + i * 0x8; case OMAP_DSS_VIDEO3: return 0x0430 + i * 0x8; + case OMAP_DSS_WB: + return 0x02A0 + i * 0x8; default: BUG(); return 0; @@ -763,6 +789,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i) case OMAP_DSS_VIDEO2: return 0x0038 + i * 0x8; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x0014 + i * 0x8; default: BUG(); @@ -783,6 +810,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i) return 0x056C + i * 0x8; case OMAP_DSS_VIDEO3: return 0x0434 + i * 0x8; + case OMAP_DSS_WB: + return 0x02A4 + i * 0x8; default: BUG(); return 0; @@ -799,6 +828,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i) case OMAP_DSS_VIDEO1: case OMAP_DSS_VIDEO2: case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x0074 + i * 0x4; default: BUG(); @@ -818,6 +848,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i) case OMAP_DSS_VIDEO2: return 0x00B4 + i * 0x4; case OMAP_DSS_VIDEO3: + case OMAP_DSS_WB: return 0x0050 + i * 0x4; default: BUG(); @@ -838,6 +869,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i) return 0x05A8 + i * 0x4; case OMAP_DSS_VIDEO3: return 0x0470 + i * 0x4; + case OMAP_DSS_WB: + return 0x02E0 + i * 0x4; default: BUG(); return 0; diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index a14528bcfea..6728892f9da 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -113,6 +113,17 @@ enum dss_dsi_content_type { DSS_DSI_CONTENT_GENERIC, }; +enum dss_writeback_channel { + DSS_WB_LCD1_MGR = 0, + DSS_WB_LCD2_MGR = 1, + DSS_WB_TV_MGR = 2, + DSS_WB_OVL0 = 3, + DSS_WB_OVL1 = 4, + DSS_WB_OVL2 = 5, + DSS_WB_OVL3 = 6, + DSS_WB_LCD3_MGR = 7, +}; + struct dss_clock_info { /* rates that we get with dividers below */ unsigned long fck; @@ -444,8 +455,9 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, bool manual_update); -int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, - bool replication, const struct omap_video_timings *mgr_timings); +int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, + bool replication, const struct omap_video_timings *mgr_timings, + bool mem_to_mem); int dispc_ovl_enable(enum omap_plane plane, bool enable); void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel); @@ -474,6 +486,15 @@ int dispc_mgr_get_clock_div(enum omap_channel channel, void dispc_mgr_setup(enum omap_channel channel, struct omap_overlay_manager_info *info); +u32 dispc_wb_get_framedone_irq(void); +bool dispc_wb_go_busy(void); +void dispc_wb_go(void); +void dispc_wb_enable(bool enable); +bool dispc_wb_is_enabled(void); +void dispc_wb_set_channel_in(enum dss_writeback_channel channel); +int dispc_wb_setup(const struct omap_dss_writeback_info *wi, + bool mem_to_mem, const struct omap_video_timings *timings); + /* VENC */ #ifdef CONFIG_OMAP2_DSS_VENC int venc_init_platform_driver(void) __init; diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index bfe7fc7b859..acbc1e1efba 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -46,6 +46,7 @@ struct omap_dss_features { const int num_mgrs; const int num_ovls; + const int num_wbs; const enum omap_display_type *supported_displays; const enum omap_dss_output_id *supported_outputs; const enum omap_color_mode *supported_color_modes; @@ -310,58 +311,80 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = { OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | OMAP_DSS_COLOR_RGBX32, + + /* OMAP_DSS_WB */ + OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U | + OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 | + OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 | + OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U | + OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY | + OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | + OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | + OMAP_DSS_COLOR_RGBX32, }; static const enum omap_overlay_caps omap2_dss_overlay_caps[] = { /* OMAP_DSS_GFX */ - 0, + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, /* OMAP_DSS_VIDEO1 */ - OMAP_DSS_OVL_CAP_SCALE, + 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_SCALE | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, }; static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = { /* OMAP_DSS_GFX */ - OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, + 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_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_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, }; static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = { /* OMAP_DSS_GFX */ - OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, + 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_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_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS | + OMAP_DSS_OVL_CAP_REPLICATION, }; static const enum omap_overlay_caps omap4_dss_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_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_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_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_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER | + OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION, }; static const char * const omap2_dss_clk_source_names[] = { @@ -698,6 +721,7 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = { .num_mgrs = 3, .num_ovls = 4, + .num_wbs = 1, .supported_displays = omap4_dss_supported_displays, .supported_outputs = omap4_dss_supported_outputs, .supported_color_modes = omap4_dss_supported_color_modes, @@ -719,6 +743,7 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = { .num_mgrs = 3, .num_ovls = 4, + .num_wbs = 1, .supported_displays = omap4_dss_supported_displays, .supported_outputs = omap4_dss_supported_outputs, .supported_color_modes = omap4_dss_supported_color_modes, @@ -740,6 +765,7 @@ static const struct omap_dss_features omap4_dss_features = { .num_mgrs = 3, .num_ovls = 4, + .num_wbs = 1, .supported_displays = omap4_dss_supported_displays, .supported_outputs = omap4_dss_supported_outputs, .supported_color_modes = omap4_dss_supported_color_modes, @@ -817,6 +843,11 @@ int dss_feat_get_num_ovls(void) return omap_current_dss_features->num_ovls; } +int dss_feat_get_num_wbs(void) +{ + return omap_current_dss_features->num_wbs; +} + unsigned long dss_feat_get_param_min(enum dss_range_param param) { return omap_current_dss_features->dss_params[param].min; diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 89df2aa860d..9218113b5e8 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -105,6 +105,7 @@ enum dss_range_param { /* DSS Feature Functions */ int dss_feat_get_num_mgrs(void); int dss_feat_get_num_ovls(void); +int dss_feat_get_num_wbs(void); unsigned long dss_feat_get_param_min(enum dss_range_param param); unsigned long dss_feat_get_param_max(enum dss_range_param param); enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); diff --git a/include/video/omapdss.h b/include/video/omapdss.h index e65e2e9e16e..3729173b7fb 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -187,6 +187,8 @@ enum omap_overlay_caps { OMAP_DSS_OVL_CAP_GLOBAL_ALPHA = 1 << 1, OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA = 1 << 2, OMAP_DSS_OVL_CAP_ZORDER = 1 << 3, + OMAP_DSS_OVL_CAP_POS = 1 << 4, + OMAP_DSS_OVL_CAP_REPLICATION = 1 << 5, }; enum omap_overlay_manager_caps { @@ -508,6 +510,19 @@ struct omap_dsi_pin_config { int pins[OMAP_DSS_MAX_DSI_PINS]; }; +struct omap_dss_writeback_info { + u32 paddr; + u32 p_uv_addr; + u16 buf_width; + u16 width; + u16 height; + enum omap_color_mode color_mode; + u8 rotation; + enum omap_dss_rotation_type rotation_type; + bool mirror; + u8 pre_mult_alpha; +}; + struct omap_dss_output { struct list_head list; |