diff options
Diffstat (limited to 'drivers')
-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 ff52702dfd2..0de9a7efcbc 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 |