aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorArchit Taneja <archit@ti.com>2012-09-26 07:28:52 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-09-26 07:58:49 -0400
commit3e8a6ff2489510f529364f3c3f8b8881d599fd5c (patch)
tree0a8a10b52fe739dbb9e3295c16b41766879c54aa /drivers/video
parent84a880fd51cb528ae7499d0e971a3d4f4587401a (diff)
OMAPDSS: DISPC: Don't pass channel out when configuring overlays
dispc_ovl_setup_common() is to be used by both overlays and writeback. We pass channel out to figure out what manager the overlay is connected to, to determine the pixel clock rate. This is used to decide the scaling limitations for that overlay. writeback doesn't have a channel out, it has a channel in field which tells where writeback gets its input from. These are 2 different fields, and this prevents us reusing the overlay configuration code for writeback. To overcome this, we now pass omap_plane to overlay related functions rather than passing channel out. We create helper functions which can derive pclk/lclk from the omap_plane id. Signed-off-by: Archit Taneja <archit@ti.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/dss/dispc.c110
1 files changed, 64 insertions, 46 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 9c23ce8aed49..d65568929ac8 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -86,13 +86,13 @@ struct dispc_features {
86 u16 sw_max; 86 u16 sw_max;
87 u16 vp_max; 87 u16 vp_max;
88 u16 hp_max; 88 u16 hp_max;
89 int (*calc_scaling) (enum omap_channel channel, 89 int (*calc_scaling) (enum omap_plane plane,
90 const struct omap_video_timings *mgr_timings, 90 const struct omap_video_timings *mgr_timings,
91 u16 width, u16 height, u16 out_width, u16 out_height, 91 u16 width, u16 height, u16 out_width, u16 out_height,
92 enum omap_color_mode color_mode, bool *five_taps, 92 enum omap_color_mode color_mode, bool *five_taps,
93 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, 93 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
94 u16 pos_x, unsigned long *core_clk); 94 u16 pos_x, unsigned long *core_clk);
95 unsigned long (*calc_core_clk) (enum omap_channel channel, 95 unsigned long (*calc_core_clk) (enum omap_plane plane,
96 u16 width, u16 height, u16 out_width, u16 out_height); 96 u16 width, u16 height, u16 out_width, u16 out_height);
97 u8 num_fifos; 97 u8 num_fifos;
98 98
@@ -236,6 +236,8 @@ static const struct {
236}; 236};
237 237
238static void _omap_dispc_set_irqs(void); 238static void _omap_dispc_set_irqs(void);
239static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
240static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
239 241
240static inline void dispc_write_reg(const u16 idx, u32 val) 242static inline void dispc_write_reg(const u16 idx, u32 val)
241{ 243{
@@ -1919,22 +1921,19 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
1919 * This function is used to avoid synclosts in OMAP3, because of some 1921 * This function is used to avoid synclosts in OMAP3, because of some
1920 * undocumented horizontal position and timing related limitations. 1922 * undocumented horizontal position and timing related limitations.
1921 */ 1923 */
1922static int check_horiz_timing_omap3(enum omap_channel channel, 1924static int check_horiz_timing_omap3(enum omap_plane plane,
1923 const struct omap_video_timings *t, u16 pos_x, 1925 const struct omap_video_timings *t, u16 pos_x,
1924 u16 width, u16 height, u16 out_width, u16 out_height) 1926 u16 width, u16 height, u16 out_width, u16 out_height)
1925{ 1927{
1926 int DS = DIV_ROUND_UP(height, out_height); 1928 int DS = DIV_ROUND_UP(height, out_height);
1927 unsigned long nonactive, lclk, pclk; 1929 unsigned long nonactive;
1928 static const u8 limits[3] = { 8, 10, 20 }; 1930 static const u8 limits[3] = { 8, 10, 20 };
1929 u64 val, blank; 1931 u64 val, blank;
1932 unsigned long pclk = dispc_plane_pclk_rate(plane);
1933 unsigned long lclk = dispc_plane_lclk_rate(plane);
1930 int i; 1934 int i;
1931 1935
1932 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; 1936 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
1933 pclk = dispc_mgr_pclk_rate(channel);
1934 if (dss_mgr_is_lcd(channel))
1935 lclk = dispc_mgr_lclk_rate(channel);
1936 else
1937 lclk = dispc_fclk_rate();
1938 1937
1939 i = 0; 1938 i = 0;
1940 if (out_height < height) 1939 if (out_height < height)
@@ -1971,13 +1970,14 @@ static int check_horiz_timing_omap3(enum omap_channel channel,
1971 return 0; 1970 return 0;
1972} 1971}
1973 1972
1974static unsigned long calc_core_clk_five_taps(enum omap_channel channel, 1973static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
1975 const struct omap_video_timings *mgr_timings, u16 width, 1974 const struct omap_video_timings *mgr_timings, u16 width,
1976 u16 height, u16 out_width, u16 out_height, 1975 u16 height, u16 out_width, u16 out_height,
1977 enum omap_color_mode color_mode) 1976 enum omap_color_mode color_mode)
1978{ 1977{
1979 u32 core_clk = 0; 1978 u32 core_clk = 0;
1980 u64 tmp, pclk = dispc_mgr_pclk_rate(channel); 1979 u64 tmp;
1980 unsigned long pclk = dispc_plane_pclk_rate(plane);
1981 1981
1982 if (height <= out_height && width <= out_width) 1982 if (height <= out_height && width <= out_width)
1983 return (unsigned long) pclk; 1983 return (unsigned long) pclk;
@@ -2011,10 +2011,10 @@ static unsigned long calc_core_clk_five_taps(enum omap_channel channel,
2011 return core_clk; 2011 return core_clk;
2012} 2012}
2013 2013
2014static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width, 2014static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width,
2015 u16 height, u16 out_width, u16 out_height) 2015 u16 height, u16 out_width, u16 out_height)
2016{ 2016{
2017 unsigned long pclk = dispc_mgr_pclk_rate(channel); 2017 unsigned long pclk = dispc_plane_pclk_rate(plane);
2018 2018
2019 if (height > out_height && width > out_width) 2019 if (height > out_height && width > out_width)
2020 return pclk * 4; 2020 return pclk * 4;
@@ -2022,11 +2022,11 @@ static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width,
2022 return pclk * 2; 2022 return pclk * 2;
2023} 2023}
2024 2024
2025static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width, 2025static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
2026 u16 height, u16 out_width, u16 out_height) 2026 u16 height, u16 out_width, u16 out_height)
2027{ 2027{
2028 unsigned int hf, vf; 2028 unsigned int hf, vf;
2029 unsigned long pclk = dispc_mgr_pclk_rate(channel); 2029 unsigned long pclk = dispc_plane_pclk_rate(plane);
2030 2030
2031 /* 2031 /*
2032 * FIXME how to determine the 'A' factor 2032 * FIXME how to determine the 'A' factor
@@ -2049,10 +2049,10 @@ static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width,
2049 return pclk * vf * hf; 2049 return pclk * vf * hf;
2050} 2050}
2051 2051
2052static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width, 2052static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
2053 u16 height, u16 out_width, u16 out_height) 2053 u16 height, u16 out_width, u16 out_height)
2054{ 2054{
2055 unsigned long pclk = dispc_mgr_pclk_rate(channel); 2055 unsigned long pclk = dispc_plane_pclk_rate(plane);
2056 2056
2057 if (width > out_width) 2057 if (width > out_width)
2058 return DIV_ROUND_UP(pclk, out_width) * width; 2058 return DIV_ROUND_UP(pclk, out_width) * width;
@@ -2060,7 +2060,7 @@ static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width,
2060 return pclk; 2060 return pclk;
2061} 2061}
2062 2062
2063static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel, 2063static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
2064 const struct omap_video_timings *mgr_timings, 2064 const struct omap_video_timings *mgr_timings,
2065 u16 width, u16 height, u16 out_width, u16 out_height, 2065 u16 width, u16 height, u16 out_width, u16 out_height,
2066 enum omap_color_mode color_mode, bool *five_taps, 2066 enum omap_color_mode color_mode, bool *five_taps,
@@ -2072,12 +2072,13 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel,
2072 int min_factor = min(*decim_x, *decim_y); 2072 int min_factor = min(*decim_x, *decim_y);
2073 const int maxsinglelinewidth = 2073 const int maxsinglelinewidth =
2074 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); 2074 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2075
2075 *five_taps = false; 2076 *five_taps = false;
2076 2077
2077 do { 2078 do {
2078 in_height = DIV_ROUND_UP(height, *decim_y); 2079 in_height = DIV_ROUND_UP(height, *decim_y);
2079 in_width = DIV_ROUND_UP(width, *decim_x); 2080 in_width = DIV_ROUND_UP(width, *decim_x);
2080 *core_clk = dispc.feat->calc_core_clk(channel, in_width, 2081 *core_clk = dispc.feat->calc_core_clk(plane, in_width,
2081 in_height, out_width, out_height); 2082 in_height, out_width, out_height);
2082 error = (in_width > maxsinglelinewidth || !*core_clk || 2083 error = (in_width > maxsinglelinewidth || !*core_clk ||
2083 *core_clk > dispc_core_clk_rate()); 2084 *core_clk > dispc_core_clk_rate());
@@ -2100,7 +2101,7 @@ static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel,
2100 return 0; 2101 return 0;
2101} 2102}
2102 2103
2103static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel, 2104static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
2104 const struct omap_video_timings *mgr_timings, 2105 const struct omap_video_timings *mgr_timings,
2105 u16 width, u16 height, u16 out_width, u16 out_height, 2106 u16 width, u16 height, u16 out_width, u16 out_height,
2106 enum omap_color_mode color_mode, bool *five_taps, 2107 enum omap_color_mode color_mode, bool *five_taps,
@@ -2116,18 +2117,19 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel,
2116 do { 2117 do {
2117 in_height = DIV_ROUND_UP(height, *decim_y); 2118 in_height = DIV_ROUND_UP(height, *decim_y);
2118 in_width = DIV_ROUND_UP(width, *decim_x); 2119 in_width = DIV_ROUND_UP(width, *decim_x);
2119 *core_clk = calc_core_clk_five_taps(channel, mgr_timings, 2120 *core_clk = calc_core_clk_five_taps(plane, mgr_timings,
2120 in_width, in_height, out_width, out_height, color_mode); 2121 in_width, in_height, out_width, out_height, color_mode);
2121 2122
2122 error = check_horiz_timing_omap3(channel, mgr_timings, pos_x, 2123 error = check_horiz_timing_omap3(plane, mgr_timings,
2123 in_width, in_height, out_width, out_height); 2124 pos_x, in_width, in_height, out_width,
2125 out_height);
2124 2126
2125 if (in_width > maxsinglelinewidth) 2127 if (in_width > maxsinglelinewidth)
2126 if (in_height > out_height && 2128 if (in_height > out_height &&
2127 in_height < out_height * 2) 2129 in_height < out_height * 2)
2128 *five_taps = false; 2130 *five_taps = false;
2129 if (!*five_taps) 2131 if (!*five_taps)
2130 *core_clk = dispc.feat->calc_core_clk(channel, in_width, 2132 *core_clk = dispc.feat->calc_core_clk(plane, in_width,
2131 in_height, out_width, out_height); 2133 in_height, out_width, out_height);
2132 2134
2133 error = (error || in_width > maxsinglelinewidth * 2 || 2135 error = (error || in_width > maxsinglelinewidth * 2 ||
@@ -2145,7 +2147,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel,
2145 } 2147 }
2146 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); 2148 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2147 2149
2148 if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, height, 2150 if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height,
2149 out_width, out_height)){ 2151 out_width, out_height)){
2150 DSSERR("horizontal timing too tight\n"); 2152 DSSERR("horizontal timing too tight\n");
2151 return -EINVAL; 2153 return -EINVAL;
@@ -2164,7 +2166,7 @@ static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel,
2164 return 0; 2166 return 0;
2165} 2167}
2166 2168
2167static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel, 2169static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
2168 const struct omap_video_timings *mgr_timings, 2170 const struct omap_video_timings *mgr_timings,
2169 u16 width, u16 height, u16 out_width, u16 out_height, 2171 u16 width, u16 height, u16 out_width, u16 out_height,
2170 enum omap_color_mode color_mode, bool *five_taps, 2172 enum omap_color_mode color_mode, bool *five_taps,
@@ -2176,9 +2178,10 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel,
2176 u16 in_height = DIV_ROUND_UP(height, *decim_y); 2178 u16 in_height = DIV_ROUND_UP(height, *decim_y);
2177 const int maxsinglelinewidth = 2179 const int maxsinglelinewidth =
2178 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); 2180 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2181 unsigned long pclk = dispc_plane_pclk_rate(plane);
2182
2183 in_width_max = dispc_core_clk_rate() / DIV_ROUND_UP(pclk, out_width);
2179 2184
2180 in_width_max = dispc_core_clk_rate() /
2181 DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), out_width);
2182 *decim_x = DIV_ROUND_UP(width, in_width_max); 2185 *decim_x = DIV_ROUND_UP(width, in_width_max);
2183 2186
2184 *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min; 2187 *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
@@ -2195,13 +2198,13 @@ static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel,
2195 return -EINVAL; 2198 return -EINVAL;
2196 } 2199 }
2197 2200
2198 *core_clk = dispc.feat->calc_core_clk(channel, in_width, in_height, 2201 *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height,
2199 out_width, out_height); 2202 out_width, out_height);
2200 return 0; 2203 return 0;
2201} 2204}
2202 2205
2203static int dispc_ovl_calc_scaling(enum omap_plane plane, 2206static int dispc_ovl_calc_scaling(enum omap_plane plane,
2204 enum omap_overlay_caps caps, enum omap_channel channel, 2207 enum omap_overlay_caps caps,
2205 const struct omap_video_timings *mgr_timings, 2208 const struct omap_video_timings *mgr_timings,
2206 u16 width, u16 height, u16 out_width, u16 out_height, 2209 u16 width, u16 height, u16 out_width, u16 out_height,
2207 enum omap_color_mode color_mode, bool *five_taps, 2210 enum omap_color_mode color_mode, bool *five_taps,
@@ -2242,9 +2245,9 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2242 if (decim_y > *y_predecim || out_height > height * 8) 2245 if (decim_y > *y_predecim || out_height > height * 8)
2243 return -EINVAL; 2246 return -EINVAL;
2244 2247
2245 ret = dispc.feat->calc_scaling(channel, mgr_timings, width, height, 2248 ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height,
2246 out_width, out_height, color_mode, five_taps, x_predecim, 2249 out_width, out_height, color_mode, five_taps,
2247 y_predecim, &decim_x, &decim_y, pos_x, &core_clk); 2250 x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk);
2248 if (ret) 2251 if (ret)
2249 return ret; 2252 return ret;
2250 2253
@@ -2265,12 +2268,11 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2265} 2268}
2266 2269
2267static int dispc_ovl_setup_common(enum omap_plane plane, 2270static int dispc_ovl_setup_common(enum omap_plane plane,
2268 enum omap_channel channel, enum omap_overlay_caps caps, 2271 enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
2269 u32 paddr, u32 p_uv_addr, u16 screen_width, int pos_x, 2272 u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
2270 int pos_y, u16 width, u16 height, u16 out_width, u16 out_height, 2273 u16 out_width, u16 out_height, enum omap_color_mode color_mode,
2271 enum omap_color_mode color_mode, u8 rotation, bool mirror, 2274 u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
2272 u8 zorder, u8 pre_mult_alpha, u8 global_alpha, 2275 u8 global_alpha, enum omap_dss_rotation_type rotation_type,
2273 enum omap_dss_rotation_type rotation_type,
2274 bool replication, const struct omap_video_timings *mgr_timings) 2276 bool replication, const struct omap_video_timings *mgr_timings)
2275{ 2277{
2276 bool five_taps = true; 2278 bool five_taps = true;
@@ -2309,7 +2311,7 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
2309 if (!dss_feat_color_mode_supported(plane, color_mode)) 2311 if (!dss_feat_color_mode_supported(plane, color_mode))
2310 return -EINVAL; 2312 return -EINVAL;
2311 2313
2312 r = dispc_ovl_calc_scaling(plane, caps, channel, mgr_timings, in_width, 2314 r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width,
2313 in_height, out_width, out_height, color_mode, 2315 in_height, out_width, out_height, color_mode,
2314 &five_taps, &x_predecim, &y_predecim, pos_x, 2316 &five_taps, &x_predecim, &y_predecim, pos_x,
2315 rotation_type); 2317 rotation_type);
@@ -2424,12 +2426,11 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
2424 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height, 2426 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
2425 oi->color_mode, oi->rotation, oi->mirror, channel, replication); 2427 oi->color_mode, oi->rotation, oi->mirror, channel, replication);
2426 2428
2427 r = dispc_ovl_setup_common(plane, channel, ovl->caps, oi->paddr, 2429 r = dispc_ovl_setup_common(plane, ovl->caps, oi->paddr, oi->p_uv_addr,
2428 oi->p_uv_addr, oi->screen_width, oi->pos_x, oi->pos_y, 2430 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
2429 oi->width, oi->height, oi->out_width, oi->out_height, 2431 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
2430 oi->color_mode, oi->rotation, oi->mirror, oi->zorder, 2432 oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
2431 oi->pre_mult_alpha, oi->global_alpha, oi->rotation_type, 2433 oi->rotation_type, replication, mgr_timings);
2432 replication, mgr_timings);
2433 2434
2434 return r; 2435 return r;
2435} 2436}
@@ -2989,6 +2990,23 @@ unsigned long dispc_core_clk_rate(void)
2989 return fclk / lcd; 2990 return fclk / lcd;
2990} 2991}
2991 2992
2993static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
2994{
2995 enum omap_channel channel = dispc_ovl_get_channel_out(plane);
2996
2997 return dispc_mgr_pclk_rate(channel);
2998}
2999
3000static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
3001{
3002 enum omap_channel channel = dispc_ovl_get_channel_out(plane);
3003
3004 if (dss_mgr_is_lcd(channel))
3005 return dispc_mgr_lclk_rate(channel);
3006 else
3007 return dispc_fclk_rate();
3008
3009}
2992static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) 3010static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
2993{ 3011{
2994 int lcd, pcd; 3012 int lcd, pcd;