diff options
| -rw-r--r-- | drivers/video/omap2/dss/dispc.c | 434 |
1 files changed, 279 insertions, 155 deletions
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index ff52702dfd2f..0de9a7efcbc4 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
| @@ -81,6 +81,23 @@ struct dispc_irq_stats { | |||
| 81 | unsigned irqs[32]; | 81 | unsigned irqs[32]; |
| 82 | }; | 82 | }; |
| 83 | 83 | ||
| 84 | struct dispc_features { | ||
| 85 | u8 sw_start; | ||
| 86 | u8 fp_start; | ||
| 87 | u8 bp_start; | ||
| 88 | u16 sw_max; | ||
| 89 | u16 vp_max; | ||
| 90 | u16 hp_max; | ||
| 91 | int (*calc_scaling) (enum omap_channel channel, | ||
| 92 | const struct omap_video_timings *mgr_timings, | ||
| 93 | u16 width, u16 height, u16 out_width, u16 out_height, | ||
| 94 | enum omap_color_mode color_mode, bool *five_taps, | ||
| 95 | int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, | ||
| 96 | u16 pos_x, unsigned long *core_clk); | ||
| 97 | unsigned long (*calc_core_clk) (enum omap_channel channel, | ||
| 98 | u16 width, u16 height, u16 out_width, u16 out_height); | ||
| 99 | }; | ||
| 100 | |||
| 84 | static struct { | 101 | static struct { |
| 85 | struct platform_device *pdev; | 102 | struct platform_device *pdev; |
| 86 | void __iomem *base; | 103 | void __iomem *base; |
| @@ -101,6 +118,8 @@ static struct { | |||
| 101 | bool ctx_valid; | 118 | bool ctx_valid; |
| 102 | u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; | 119 | u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; |
| 103 | 120 | ||
| 121 | const struct dispc_features *feat; | ||
| 122 | |||
| 104 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 123 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
| 105 | spinlock_t irq_stats_lock; | 124 | spinlock_t irq_stats_lock; |
| 106 | struct dispc_irq_stats irq_stats; | 125 | struct dispc_irq_stats irq_stats; |
| @@ -1939,7 +1958,18 @@ static unsigned long calc_core_clk_five_taps(enum omap_channel channel, | |||
| 1939 | return core_clk; | 1958 | return core_clk; |
| 1940 | } | 1959 | } |
| 1941 | 1960 | ||
| 1942 | static unsigned long calc_core_clk(enum omap_channel channel, u16 width, | 1961 | static unsigned long calc_core_clk_24xx(enum omap_channel channel, u16 width, |
| 1962 | u16 height, u16 out_width, u16 out_height) | ||
| 1963 | { | ||
| 1964 | unsigned long pclk = dispc_mgr_pclk_rate(channel); | ||
| 1965 | |||
| 1966 | if (height > out_height && width > out_width) | ||
| 1967 | return pclk * 4; | ||
| 1968 | else | ||
| 1969 | return pclk * 2; | ||
| 1970 | } | ||
| 1971 | |||
| 1972 | static unsigned long calc_core_clk_34xx(enum omap_channel channel, u16 width, | ||
| 1943 | u16 height, u16 out_width, u16 out_height) | 1973 | u16 height, u16 out_width, u16 out_height) |
| 1944 | { | 1974 | { |
| 1945 | unsigned int hf, vf; | 1975 | unsigned int hf, vf; |
| @@ -1958,25 +1988,163 @@ static unsigned long calc_core_clk(enum omap_channel channel, u16 width, | |||
| 1958 | hf = 2; | 1988 | hf = 2; |
| 1959 | else | 1989 | else |
| 1960 | hf = 1; | 1990 | hf = 1; |
| 1961 | |||
| 1962 | if (height > out_height) | 1991 | if (height > out_height) |
| 1963 | vf = 2; | 1992 | vf = 2; |
| 1964 | else | 1993 | else |
| 1965 | vf = 1; | 1994 | vf = 1; |
| 1966 | 1995 | ||
| 1967 | if (cpu_is_omap24xx()) { | 1996 | return pclk * vf * hf; |
| 1968 | if (vf > 1 && hf > 1) | 1997 | } |
| 1969 | return pclk * 4; | 1998 | |
| 1970 | else | 1999 | static unsigned long calc_core_clk_44xx(enum omap_channel channel, u16 width, |
| 1971 | return pclk * 2; | 2000 | u16 height, u16 out_width, u16 out_height) |
| 1972 | } else if (cpu_is_omap34xx()) { | 2001 | { |
| 1973 | return pclk * vf * hf; | 2002 | unsigned long pclk = dispc_mgr_pclk_rate(channel); |
| 1974 | } else { | 2003 | |
| 1975 | if (hf > 1) | 2004 | if (width > out_width) |
| 1976 | return DIV_ROUND_UP(pclk, out_width) * width; | 2005 | return DIV_ROUND_UP(pclk, out_width) * width; |
| 1977 | else | 2006 | else |
| 1978 | return pclk; | 2007 | return pclk; |
| 2008 | } | ||
| 2009 | |||
| 2010 | static int dispc_ovl_calc_scaling_24xx(enum omap_channel channel, | ||
| 2011 | const struct omap_video_timings *mgr_timings, | ||
| 2012 | u16 width, u16 height, u16 out_width, u16 out_height, | ||
| 2013 | enum omap_color_mode color_mode, bool *five_taps, | ||
| 2014 | int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, | ||
| 2015 | u16 pos_x, unsigned long *core_clk) | ||
| 2016 | { | ||
| 2017 | int error; | ||
| 2018 | u16 in_width, in_height; | ||
| 2019 | int min_factor = min(*decim_x, *decim_y); | ||
| 2020 | const int maxsinglelinewidth = | ||
| 2021 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); | ||
| 2022 | *five_taps = false; | ||
| 2023 | |||
| 2024 | do { | ||
| 2025 | in_height = DIV_ROUND_UP(height, *decim_y); | ||
| 2026 | in_width = DIV_ROUND_UP(width, *decim_x); | ||
| 2027 | *core_clk = dispc.feat->calc_core_clk(channel, in_width, | ||
| 2028 | in_height, out_width, out_height); | ||
| 2029 | error = (in_width > maxsinglelinewidth || !*core_clk || | ||
| 2030 | *core_clk > dispc_core_clk_rate()); | ||
| 2031 | if (error) { | ||
| 2032 | if (*decim_x == *decim_y) { | ||
| 2033 | *decim_x = min_factor; | ||
| 2034 | ++*decim_y; | ||
| 2035 | } else { | ||
| 2036 | swap(*decim_x, *decim_y); | ||
| 2037 | if (*decim_x < *decim_y) | ||
| 2038 | ++*decim_x; | ||
| 2039 | } | ||
| 2040 | } | ||
| 2041 | } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); | ||
| 2042 | |||
| 2043 | if (in_width > maxsinglelinewidth) { | ||
| 2044 | DSSERR("Cannot scale max input width exceeded"); | ||
| 2045 | return -EINVAL; | ||
| 2046 | } | ||
| 2047 | return 0; | ||
| 2048 | } | ||
| 2049 | |||
| 2050 | static int dispc_ovl_calc_scaling_34xx(enum omap_channel channel, | ||
| 2051 | const struct omap_video_timings *mgr_timings, | ||
| 2052 | u16 width, u16 height, u16 out_width, u16 out_height, | ||
| 2053 | enum omap_color_mode color_mode, bool *five_taps, | ||
| 2054 | int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, | ||
| 2055 | u16 pos_x, unsigned long *core_clk) | ||
| 2056 | { | ||
| 2057 | int error; | ||
| 2058 | u16 in_width, in_height; | ||
| 2059 | int min_factor = min(*decim_x, *decim_y); | ||
| 2060 | const int maxsinglelinewidth = | ||
| 2061 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); | ||
| 2062 | |||
| 2063 | do { | ||
| 2064 | in_height = DIV_ROUND_UP(height, *decim_y); | ||
| 2065 | in_width = DIV_ROUND_UP(width, *decim_x); | ||
| 2066 | *core_clk = calc_core_clk_five_taps(channel, mgr_timings, | ||
| 2067 | in_width, in_height, out_width, out_height, color_mode); | ||
| 2068 | |||
| 2069 | error = check_horiz_timing_omap3(channel, mgr_timings, pos_x, | ||
| 2070 | in_width, in_height, out_width, out_height); | ||
| 2071 | |||
| 2072 | if (in_width > maxsinglelinewidth) | ||
| 2073 | if (in_height > out_height && | ||
| 2074 | in_height < out_height * 2) | ||
| 2075 | *five_taps = false; | ||
| 2076 | if (!*five_taps) | ||
| 2077 | *core_clk = dispc.feat->calc_core_clk(channel, in_width, | ||
| 2078 | in_height, out_width, out_height); | ||
| 2079 | |||
| 2080 | error = (error || in_width > maxsinglelinewidth * 2 || | ||
| 2081 | (in_width > maxsinglelinewidth && *five_taps) || | ||
| 2082 | !*core_clk || *core_clk > dispc_core_clk_rate()); | ||
| 2083 | if (error) { | ||
| 2084 | if (*decim_x == *decim_y) { | ||
| 2085 | *decim_x = min_factor; | ||
| 2086 | ++*decim_y; | ||
| 2087 | } else { | ||
| 2088 | swap(*decim_x, *decim_y); | ||
| 2089 | if (*decim_x < *decim_y) | ||
| 2090 | ++*decim_x; | ||
| 2091 | } | ||
| 2092 | } | ||
| 2093 | } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error); | ||
| 2094 | |||
| 2095 | if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, height, | ||
| 2096 | out_width, out_height)){ | ||
| 2097 | DSSERR("horizontal timing too tight\n"); | ||
| 2098 | return -EINVAL; | ||
| 2099 | } | ||
| 2100 | |||
| 2101 | if (in_width > (maxsinglelinewidth * 2)) { | ||
| 2102 | DSSERR("Cannot setup scaling"); | ||
| 2103 | DSSERR("width exceeds maximum width possible"); | ||
| 2104 | return -EINVAL; | ||
| 2105 | } | ||
| 2106 | |||
| 2107 | if (in_width > maxsinglelinewidth && *five_taps) { | ||
| 2108 | DSSERR("cannot setup scaling with five taps"); | ||
| 2109 | return -EINVAL; | ||
| 1979 | } | 2110 | } |
| 2111 | return 0; | ||
| 2112 | } | ||
| 2113 | |||
| 2114 | static int dispc_ovl_calc_scaling_44xx(enum omap_channel channel, | ||
| 2115 | const struct omap_video_timings *mgr_timings, | ||
| 2116 | u16 width, u16 height, u16 out_width, u16 out_height, | ||
| 2117 | enum omap_color_mode color_mode, bool *five_taps, | ||
| 2118 | int *x_predecim, int *y_predecim, int *decim_x, int *decim_y, | ||
| 2119 | u16 pos_x, unsigned long *core_clk) | ||
| 2120 | { | ||
| 2121 | u16 in_width, in_width_max; | ||
| 2122 | int decim_x_min = *decim_x; | ||
| 2123 | u16 in_height = DIV_ROUND_UP(height, *decim_y); | ||
| 2124 | const int maxsinglelinewidth = | ||
| 2125 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); | ||
| 2126 | |||
| 2127 | in_width_max = dispc_core_clk_rate() / | ||
| 2128 | DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), out_width); | ||
| 2129 | *decim_x = DIV_ROUND_UP(width, in_width_max); | ||
| 2130 | |||
| 2131 | *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min; | ||
| 2132 | if (*decim_x > *x_predecim) | ||
| 2133 | return -EINVAL; | ||
| 2134 | |||
| 2135 | do { | ||
| 2136 | in_width = DIV_ROUND_UP(width, *decim_x); | ||
| 2137 | } while (*decim_x <= *x_predecim && | ||
| 2138 | in_width > maxsinglelinewidth && ++*decim_x); | ||
| 2139 | |||
| 2140 | if (in_width > maxsinglelinewidth) { | ||
| 2141 | DSSERR("Cannot scale width exceeds max line width"); | ||
| 2142 | return -EINVAL; | ||
| 2143 | } | ||
| 2144 | |||
| 2145 | *core_clk = dispc.feat->calc_core_clk(channel, in_width, in_height, | ||
| 2146 | out_width, out_height); | ||
| 2147 | return 0; | ||
| 1980 | } | 2148 | } |
| 1981 | 2149 | ||
| 1982 | static int dispc_ovl_calc_scaling(enum omap_plane plane, | 2150 | static int dispc_ovl_calc_scaling(enum omap_plane plane, |
| @@ -1988,12 +2156,9 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, | |||
| 1988 | { | 2156 | { |
| 1989 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); | 2157 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); |
| 1990 | const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); | 2158 | const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); |
| 1991 | const int maxsinglelinewidth = | ||
| 1992 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); | ||
| 1993 | const int max_decim_limit = 16; | 2159 | const int max_decim_limit = 16; |
| 1994 | unsigned long core_clk = 0; | 2160 | unsigned long core_clk = 0; |
| 1995 | int decim_x, decim_y, error, min_factor; | 2161 | int decim_x, decim_y, ret; |
| 1996 | u16 in_width, in_height, in_width_max = 0; | ||
| 1997 | 2162 | ||
| 1998 | if (width == out_width && height == out_height) | 2163 | if (width == out_width && height == out_height) |
| 1999 | return 0; | 2164 | return 0; |
| @@ -2017,118 +2182,17 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane, | |||
| 2017 | decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale); | 2182 | decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale); |
| 2018 | decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale); | 2183 | decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale); |
| 2019 | 2184 | ||
| 2020 | min_factor = min(decim_x, decim_y); | ||
| 2021 | |||
| 2022 | if (decim_x > *x_predecim || out_width > width * 8) | 2185 | if (decim_x > *x_predecim || out_width > width * 8) |
| 2023 | return -EINVAL; | 2186 | return -EINVAL; |
| 2024 | 2187 | ||
| 2025 | if (decim_y > *y_predecim || out_height > height * 8) | 2188 | if (decim_y > *y_predecim || out_height > height * 8) |
| 2026 | return -EINVAL; | 2189 | return -EINVAL; |
| 2027 | 2190 | ||
| 2028 | if (cpu_is_omap24xx()) { | 2191 | ret = dispc.feat->calc_scaling(channel, mgr_timings, width, height, |
| 2029 | *five_taps = false; | 2192 | out_width, out_height, color_mode, five_taps, x_predecim, |
| 2030 | 2193 | y_predecim, &decim_x, &decim_y, pos_x, &core_clk); | |
| 2031 | do { | 2194 | if (ret) |
| 2032 | in_height = DIV_ROUND_UP(height, decim_y); | 2195 | return ret; |
| 2033 | in_width = DIV_ROUND_UP(width, decim_x); | ||
| 2034 | core_clk = calc_core_clk(channel, in_width, in_height, | ||
| 2035 | out_width, out_height); | ||
| 2036 | error = (in_width > maxsinglelinewidth || !core_clk || | ||
| 2037 | core_clk > dispc_core_clk_rate()); | ||
| 2038 | if (error) { | ||
| 2039 | if (decim_x == decim_y) { | ||
| 2040 | decim_x = min_factor; | ||
| 2041 | decim_y++; | ||
| 2042 | } else { | ||
| 2043 | swap(decim_x, decim_y); | ||
| 2044 | if (decim_x < decim_y) | ||
| 2045 | decim_x++; | ||
| 2046 | } | ||
| 2047 | } | ||
| 2048 | } while (decim_x <= *x_predecim && decim_y <= *y_predecim && | ||
| 2049 | error); | ||
| 2050 | |||
| 2051 | if (in_width > maxsinglelinewidth) { | ||
| 2052 | DSSERR("Cannot scale max input width exceeded"); | ||
| 2053 | return -EINVAL; | ||
| 2054 | } | ||
| 2055 | } else if (cpu_is_omap34xx()) { | ||
| 2056 | |||
| 2057 | do { | ||
| 2058 | in_height = DIV_ROUND_UP(height, decim_y); | ||
| 2059 | in_width = DIV_ROUND_UP(width, decim_x); | ||
| 2060 | core_clk = calc_core_clk_five_taps(channel, mgr_timings, | ||
| 2061 | in_width, in_height, out_width, out_height, | ||
| 2062 | color_mode); | ||
| 2063 | |||
| 2064 | error = check_horiz_timing_omap3(channel, mgr_timings, | ||
| 2065 | pos_x, in_width, in_height, out_width, | ||
| 2066 | out_height); | ||
| 2067 | |||
| 2068 | if (in_width > maxsinglelinewidth) | ||
| 2069 | if (in_height > out_height && | ||
| 2070 | in_height < out_height * 2) | ||
| 2071 | *five_taps = false; | ||
| 2072 | if (!*five_taps) | ||
| 2073 | core_clk = calc_core_clk(channel, in_width, | ||
| 2074 | in_height, out_width, out_height); | ||
| 2075 | error = (error || in_width > maxsinglelinewidth * 2 || | ||
| 2076 | (in_width > maxsinglelinewidth && *five_taps) || | ||
| 2077 | !core_clk || core_clk > dispc_core_clk_rate()); | ||
| 2078 | if (error) { | ||
| 2079 | if (decim_x == decim_y) { | ||
| 2080 | decim_x = min_factor; | ||
| 2081 | decim_y++; | ||
| 2082 | } else { | ||
| 2083 | swap(decim_x, decim_y); | ||
| 2084 | if (decim_x < decim_y) | ||
| 2085 | decim_x++; | ||
| 2086 | } | ||
| 2087 | } | ||
| 2088 | } while (decim_x <= *x_predecim && decim_y <= *y_predecim | ||
| 2089 | && error); | ||
| 2090 | |||
| 2091 | if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width, | ||
| 2092 | height, out_width, out_height)){ | ||
| 2093 | DSSERR("horizontal timing too tight\n"); | ||
| 2094 | return -EINVAL; | ||
| 2095 | } | ||
| 2096 | |||
| 2097 | if (in_width > (maxsinglelinewidth * 2)) { | ||
| 2098 | DSSERR("Cannot setup scaling"); | ||
| 2099 | DSSERR("width exceeds maximum width possible"); | ||
| 2100 | return -EINVAL; | ||
| 2101 | } | ||
| 2102 | |||
| 2103 | if (in_width > maxsinglelinewidth && *five_taps) { | ||
| 2104 | DSSERR("cannot setup scaling with five taps"); | ||
| 2105 | return -EINVAL; | ||
| 2106 | } | ||
| 2107 | } else { | ||
| 2108 | int decim_x_min = decim_x; | ||
| 2109 | in_height = DIV_ROUND_UP(height, decim_y); | ||
| 2110 | in_width_max = dispc_core_clk_rate() / | ||
| 2111 | DIV_ROUND_UP(dispc_mgr_pclk_rate(channel), | ||
| 2112 | out_width); | ||
| 2113 | decim_x = DIV_ROUND_UP(width, in_width_max); | ||
| 2114 | |||
| 2115 | decim_x = decim_x > decim_x_min ? decim_x : decim_x_min; | ||
| 2116 | if (decim_x > *x_predecim) | ||
| 2117 | return -EINVAL; | ||
| 2118 | |||
| 2119 | do { | ||
| 2120 | in_width = DIV_ROUND_UP(width, decim_x); | ||
| 2121 | } while (decim_x <= *x_predecim && | ||
| 2122 | in_width > maxsinglelinewidth && decim_x++); | ||
| 2123 | |||
| 2124 | if (in_width > maxsinglelinewidth) { | ||
| 2125 | DSSERR("Cannot scale width exceeds max line width"); | ||
| 2126 | return -EINVAL; | ||
| 2127 | } | ||
| 2128 | |||
| 2129 | core_clk = calc_core_clk(channel, in_width, in_height, | ||
| 2130 | out_width, out_height); | ||
| 2131 | } | ||
| 2132 | 2196 | ||
| 2133 | DSSDBG("required core clk rate = %lu Hz\n", core_clk); | 2197 | DSSDBG("required core clk rate = %lu Hz\n", core_clk); |
| 2134 | DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate()); | 2198 | DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate()); |
| @@ -2604,24 +2668,13 @@ static bool _dispc_mgr_size_ok(u16 width, u16 height) | |||
| 2604 | static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, | 2668 | static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, |
| 2605 | int vsw, int vfp, int vbp) | 2669 | int vsw, int vfp, int vbp) |
| 2606 | { | 2670 | { |
| 2607 | if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { | 2671 | if (hsw < 1 || hsw > dispc.feat->sw_max || |
| 2608 | if (hsw < 1 || hsw > 64 || | 2672 | hfp < 1 || hfp > dispc.feat->hp_max || |
| 2609 | hfp < 1 || hfp > 256 || | 2673 | hbp < 1 || hbp > dispc.feat->hp_max || |
| 2610 | hbp < 1 || hbp > 256 || | 2674 | vsw < 1 || vsw > dispc.feat->sw_max || |
| 2611 | vsw < 1 || vsw > 64 || | 2675 | vfp < 0 || vfp > dispc.feat->vp_max || |
| 2612 | vfp < 0 || vfp > 255 || | 2676 | vbp < 0 || vbp > dispc.feat->vp_max) |
| 2613 | vbp < 0 || vbp > 255) | 2677 | return false; |
| 2614 | return false; | ||
| 2615 | } else { | ||
| 2616 | if (hsw < 1 || hsw > 256 || | ||
| 2617 | hfp < 1 || hfp > 4096 || | ||
| 2618 | hbp < 1 || hbp > 4096 || | ||
| 2619 | vsw < 1 || vsw > 256 || | ||
| 2620 | vfp < 0 || vfp > 4095 || | ||
| 2621 | vbp < 0 || vbp > 4095) | ||
| 2622 | return false; | ||
| 2623 | } | ||
| 2624 | |||
| 2625 | return true; | 2678 | return true; |
| 2626 | } | 2679 | } |
| 2627 | 2680 | ||
| @@ -2653,19 +2706,12 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, | |||
| 2653 | u32 timing_h, timing_v, l; | 2706 | u32 timing_h, timing_v, l; |
| 2654 | bool onoff, rf, ipc; | 2707 | bool onoff, rf, ipc; |
| 2655 | 2708 | ||
| 2656 | if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { | 2709 | timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) | |
| 2657 | timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) | | 2710 | FLD_VAL(hfp-1, dispc.feat->fp_start, 8) | |
| 2658 | FLD_VAL(hbp-1, 27, 20); | 2711 | FLD_VAL(hbp-1, dispc.feat->bp_start, 20); |
| 2659 | 2712 | timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) | | |
| 2660 | timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) | | 2713 | FLD_VAL(vfp, dispc.feat->fp_start, 8) | |
| 2661 | FLD_VAL(vbp, 27, 20); | 2714 | FLD_VAL(vbp, dispc.feat->bp_start, 20); |
| 2662 | } else { | ||
| 2663 | timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) | | ||
| 2664 | FLD_VAL(hbp-1, 31, 20); | ||
| 2665 | |||
| 2666 | timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) | | ||
| 2667 | FLD_VAL(vbp, 31, 20); | ||
| 2668 | } | ||
| 2669 | 2715 | ||
| 2670 | dispc_write_reg(DISPC_TIMING_H(channel), timing_h); | 2716 | dispc_write_reg(DISPC_TIMING_H(channel), timing_h); |
| 2671 | dispc_write_reg(DISPC_TIMING_V(channel), timing_v); | 2717 | dispc_write_reg(DISPC_TIMING_V(channel), timing_v); |
| @@ -3671,6 +3717,80 @@ static void _omap_dispc_initial_config(void) | |||
| 3671 | dispc_ovl_enable_zorder_planes(); | 3717 | dispc_ovl_enable_zorder_planes(); |
| 3672 | } | 3718 | } |
| 3673 | 3719 | ||
| 3720 | static const struct dispc_features omap24xx_dispc_feats __initconst = { | ||
| 3721 | .sw_start = 5, | ||
| 3722 | .fp_start = 15, | ||
| 3723 | .bp_start = 27, | ||
| 3724 | .sw_max = 64, | ||
| 3725 | .vp_max = 255, | ||
| 3726 | .hp_max = 256, | ||
| 3727 | .calc_scaling = dispc_ovl_calc_scaling_24xx, | ||
| 3728 | .calc_core_clk = calc_core_clk_24xx, | ||
| 3729 | }; | ||
| 3730 | |||
| 3731 | static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { | ||
| 3732 | .sw_start = 5, | ||
| 3733 | .fp_start = 15, | ||
| 3734 | .bp_start = 27, | ||
| 3735 | .sw_max = 64, | ||
| 3736 | .vp_max = 255, | ||
| 3737 | .hp_max = 256, | ||
| 3738 | .calc_scaling = dispc_ovl_calc_scaling_34xx, | ||
| 3739 | .calc_core_clk = calc_core_clk_34xx, | ||
| 3740 | }; | ||
| 3741 | |||
| 3742 | static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { | ||
| 3743 | .sw_start = 7, | ||
| 3744 | .fp_start = 19, | ||
| 3745 | .bp_start = 31, | ||
| 3746 | .sw_max = 256, | ||
| 3747 | .vp_max = 4095, | ||
| 3748 | .hp_max = 4096, | ||
| 3749 | .calc_scaling = dispc_ovl_calc_scaling_34xx, | ||
| 3750 | .calc_core_clk = calc_core_clk_34xx, | ||
| 3751 | }; | ||
| 3752 | |||
| 3753 | static const struct dispc_features omap44xx_dispc_feats __initconst = { | ||
| 3754 | .sw_start = 7, | ||
| 3755 | .fp_start = 19, | ||
| 3756 | .bp_start = 31, | ||
| 3757 | .sw_max = 256, | ||
| 3758 | .vp_max = 4095, | ||
| 3759 | .hp_max = 4096, | ||
| 3760 | .calc_scaling = dispc_ovl_calc_scaling_44xx, | ||
| 3761 | .calc_core_clk = calc_core_clk_44xx, | ||
| 3762 | }; | ||
| 3763 | |||
| 3764 | static int __init dispc_init_features(struct device *dev) | ||
| 3765 | { | ||
| 3766 | const struct dispc_features *src; | ||
| 3767 | struct dispc_features *dst; | ||
| 3768 | |||
| 3769 | dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL); | ||
| 3770 | if (!dst) { | ||
| 3771 | dev_err(dev, "Failed to allocate DISPC Features\n"); | ||
| 3772 | return -ENOMEM; | ||
| 3773 | } | ||
| 3774 | |||
| 3775 | if (cpu_is_omap24xx()) { | ||
| 3776 | src = &omap24xx_dispc_feats; | ||
| 3777 | } else if (cpu_is_omap34xx()) { | ||
| 3778 | if (omap_rev() < OMAP3430_REV_ES3_0) | ||
| 3779 | src = &omap34xx_rev1_0_dispc_feats; | ||
| 3780 | else | ||
| 3781 | src = &omap34xx_rev3_0_dispc_feats; | ||
| 3782 | } else if (cpu_is_omap44xx()) { | ||
| 3783 | src = &omap44xx_dispc_feats; | ||
| 3784 | } else { | ||
| 3785 | return -ENODEV; | ||
| 3786 | } | ||
| 3787 | |||
| 3788 | memcpy(dst, src, sizeof(*dst)); | ||
| 3789 | dispc.feat = dst; | ||
| 3790 | |||
| 3791 | return 0; | ||
| 3792 | } | ||
| 3793 | |||
| 3674 | /* DISPC HW IP initialisation */ | 3794 | /* DISPC HW IP initialisation */ |
| 3675 | static int __init omap_dispchw_probe(struct platform_device *pdev) | 3795 | static int __init omap_dispchw_probe(struct platform_device *pdev) |
| 3676 | { | 3796 | { |
| @@ -3681,6 +3801,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev) | |||
| 3681 | 3801 | ||
| 3682 | dispc.pdev = pdev; | 3802 | dispc.pdev = pdev; |
| 3683 | 3803 | ||
| 3804 | r = dispc_init_features(&dispc.pdev->dev); | ||
| 3805 | if (r) | ||
| 3806 | return r; | ||
| 3807 | |||
| 3684 | spin_lock_init(&dispc.irq_lock); | 3808 | spin_lock_init(&dispc.irq_lock); |
| 3685 | 3809 | ||
| 3686 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 3810 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
