diff options
author | Dave Airlie <airlied@redhat.com> | 2016-09-27 21:23:15 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-09-27 21:23:15 -0400 |
commit | a4a7fbb4015d8f5726ff9c97a97f7ffbdc3f271e (patch) | |
tree | 9638e02f1d641ac42425b8897e1e2891a35cb616 | |
parent | 378db830c3cc5c05e2c176274b0d2fcee0b133f3 (diff) | |
parent | f0188ef8301ccbb128bbfd10751a9aeca8c9172e (diff) |
Merge tag 'sunxi-drm-fixes-for-4.9' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into drm-next
Allwinner sun4i DRM fixes for 4.9
A few fixes for the sun4i drm driver that range, including some fixes that
might prevent multiple planes from working depending on the sequence where
they are enabled.
* tag 'sunxi-drm-fixes-for-4.9' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux:
drm/sun4i: Fix the high buffer address mask
drm/sun4i: tv: Check mode pointer
drm/sun4i: Fix formats usable by the primary plane
drm/sun4i: dotclock: Round to closest clock rate
drm/sun4i: Fix sparse warnings
drm/sun4i: dotclock: Allow divider = 127
drm/sun4i: dotclock: Fix clock rate read back calcation
drm/sun4i: backend: remove redundant dev_err call in sun4i_backend_bind()
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_backend.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_backend.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_dotclock.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_layer.c | 56 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tv.c | 46 |
5 files changed, 79 insertions, 47 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 91a702225ded..32c0584e3c35 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c | |||
@@ -83,8 +83,13 @@ void sun4i_backend_layer_enable(struct sun4i_backend *backend, | |||
83 | } | 83 | } |
84 | EXPORT_SYMBOL(sun4i_backend_layer_enable); | 84 | EXPORT_SYMBOL(sun4i_backend_layer_enable); |
85 | 85 | ||
86 | static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode) | 86 | static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane, |
87 | u32 format, u32 *mode) | ||
87 | { | 88 | { |
89 | if ((plane->type == DRM_PLANE_TYPE_PRIMARY) && | ||
90 | (format == DRM_FORMAT_ARGB8888)) | ||
91 | format = DRM_FORMAT_XRGB8888; | ||
92 | |||
88 | switch (format) { | 93 | switch (format) { |
89 | case DRM_FORMAT_ARGB8888: | 94 | case DRM_FORMAT_ARGB8888: |
90 | *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888; | 95 | *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888; |
@@ -164,7 +169,7 @@ int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, | |||
164 | DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n", | 169 | DRM_DEBUG_DRIVER("Switching display backend interlaced mode %s\n", |
165 | interlaced ? "on" : "off"); | 170 | interlaced ? "on" : "off"); |
166 | 171 | ||
167 | ret = sun4i_backend_drm_format_to_layer(fb->pixel_format, &val); | 172 | ret = sun4i_backend_drm_format_to_layer(plane, fb->pixel_format, &val); |
168 | if (ret) { | 173 | if (ret) { |
169 | DRM_DEBUG_DRIVER("Invalid format\n"); | 174 | DRM_DEBUG_DRIVER("Invalid format\n"); |
170 | return val; | 175 | return val; |
@@ -288,10 +293,8 @@ static int sun4i_backend_bind(struct device *dev, struct device *master, | |||
288 | 293 | ||
289 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 294 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
290 | regs = devm_ioremap_resource(dev, res); | 295 | regs = devm_ioremap_resource(dev, res); |
291 | if (IS_ERR(regs)) { | 296 | if (IS_ERR(regs)) |
292 | dev_err(dev, "Couldn't map the backend registers\n"); | ||
293 | return PTR_ERR(regs); | 297 | return PTR_ERR(regs); |
294 | } | ||
295 | 298 | ||
296 | backend->regs = devm_regmap_init_mmio(dev, regs, | 299 | backend->regs = devm_regmap_init_mmio(dev, regs, |
297 | &sun4i_backend_regmap_config); | 300 | &sun4i_backend_regmap_config); |
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index e00718627748..83e63cc702b4 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h | |||
@@ -52,8 +52,8 @@ | |||
52 | #define SUN4I_BACKEND_LAYFB_L32ADD_REG(l) (0x850 + (0x4 * (l))) | 52 | #define SUN4I_BACKEND_LAYFB_L32ADD_REG(l) (0x850 + (0x4 * (l))) |
53 | 53 | ||
54 | #define SUN4I_BACKEND_LAYFB_H4ADD_REG 0x860 | 54 | #define SUN4I_BACKEND_LAYFB_H4ADD_REG 0x860 |
55 | #define SUN4I_BACKEND_LAYFB_H4ADD_MSK(l) GENMASK(3 + ((l) * 8), 0) | 55 | #define SUN4I_BACKEND_LAYFB_H4ADD_MSK(l) GENMASK(3 + ((l) * 8), (l) * 8) |
56 | #define SUN4I_BACKEND_LAYFB_H4ADD(l, val) ((val) << ((l) * 8)) | 56 | #define SUN4I_BACKEND_LAYFB_H4ADD(l, val) ((val) << ((l) * 8)) |
57 | 57 | ||
58 | #define SUN4I_BACKEND_REGBUFFCTL_REG 0x870 | 58 | #define SUN4I_BACKEND_REGBUFFCTL_REG 0x870 |
59 | #define SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS BIT(1) | 59 | #define SUN4I_BACKEND_REGBUFFCTL_AUTOLOAD_DIS BIT(1) |
diff --git a/drivers/gpu/drm/sun4i/sun4i_dotclock.c b/drivers/gpu/drm/sun4i/sun4i_dotclock.c index 4332da48b1b3..d401156490f3 100644 --- a/drivers/gpu/drm/sun4i/sun4i_dotclock.c +++ b/drivers/gpu/drm/sun4i/sun4i_dotclock.c | |||
@@ -62,7 +62,7 @@ static unsigned long sun4i_dclk_recalc_rate(struct clk_hw *hw, | |||
62 | regmap_read(dclk->regmap, SUN4I_TCON0_DCLK_REG, &val); | 62 | regmap_read(dclk->regmap, SUN4I_TCON0_DCLK_REG, &val); |
63 | 63 | ||
64 | val >>= SUN4I_TCON0_DCLK_DIV_SHIFT; | 64 | val >>= SUN4I_TCON0_DCLK_DIV_SHIFT; |
65 | val &= SUN4I_TCON0_DCLK_DIV_WIDTH; | 65 | val &= (1 << SUN4I_TCON0_DCLK_DIV_WIDTH) - 1; |
66 | 66 | ||
67 | if (!val) | 67 | if (!val) |
68 | val = 1; | 68 | val = 1; |
@@ -77,7 +77,7 @@ static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate, | |||
77 | u8 best_div = 1; | 77 | u8 best_div = 1; |
78 | int i; | 78 | int i; |
79 | 79 | ||
80 | for (i = 6; i < 127; i++) { | 80 | for (i = 6; i <= 127; i++) { |
81 | unsigned long ideal = rate * i; | 81 | unsigned long ideal = rate * i; |
82 | unsigned long rounded; | 82 | unsigned long rounded; |
83 | 83 | ||
@@ -90,7 +90,8 @@ static long sun4i_dclk_round_rate(struct clk_hw *hw, unsigned long rate, | |||
90 | goto out; | 90 | goto out; |
91 | } | 91 | } |
92 | 92 | ||
93 | if ((rounded < ideal) && (rounded > best_parent)) { | 93 | if (abs(rate - rounded / i) < |
94 | abs(rate - best_parent / best_div)) { | ||
94 | best_parent = rounded; | 95 | best_parent = rounded; |
95 | best_div = i; | 96 | best_div = i; |
96 | } | 97 | } |
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 068ab806309b..f0035bf5efea 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c | |||
@@ -19,7 +19,12 @@ | |||
19 | #include "sun4i_drv.h" | 19 | #include "sun4i_drv.h" |
20 | #include "sun4i_layer.h" | 20 | #include "sun4i_layer.h" |
21 | 21 | ||
22 | #define SUN4I_NUM_LAYERS 2 | 22 | struct sun4i_plane_desc { |
23 | enum drm_plane_type type; | ||
24 | u8 pipe; | ||
25 | const uint32_t *formats; | ||
26 | uint32_t nformats; | ||
27 | }; | ||
23 | 28 | ||
24 | static int sun4i_backend_layer_atomic_check(struct drm_plane *plane, | 29 | static int sun4i_backend_layer_atomic_check(struct drm_plane *plane, |
25 | struct drm_plane_state *state) | 30 | struct drm_plane_state *state) |
@@ -65,14 +70,35 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = { | |||
65 | .update_plane = drm_atomic_helper_update_plane, | 70 | .update_plane = drm_atomic_helper_update_plane, |
66 | }; | 71 | }; |
67 | 72 | ||
68 | static const uint32_t sun4i_backend_layer_formats[] = { | 73 | static const uint32_t sun4i_backend_layer_formats_primary[] = { |
69 | DRM_FORMAT_ARGB8888, | 74 | DRM_FORMAT_ARGB8888, |
75 | DRM_FORMAT_RGB888, | ||
70 | DRM_FORMAT_XRGB8888, | 76 | DRM_FORMAT_XRGB8888, |
77 | }; | ||
78 | |||
79 | static const uint32_t sun4i_backend_layer_formats_overlay[] = { | ||
80 | DRM_FORMAT_ARGB8888, | ||
71 | DRM_FORMAT_RGB888, | 81 | DRM_FORMAT_RGB888, |
82 | DRM_FORMAT_XRGB8888, | ||
83 | }; | ||
84 | |||
85 | static const struct sun4i_plane_desc sun4i_backend_planes[] = { | ||
86 | { | ||
87 | .type = DRM_PLANE_TYPE_PRIMARY, | ||
88 | .pipe = 0, | ||
89 | .formats = sun4i_backend_layer_formats_primary, | ||
90 | .nformats = ARRAY_SIZE(sun4i_backend_layer_formats_primary), | ||
91 | }, | ||
92 | { | ||
93 | .type = DRM_PLANE_TYPE_OVERLAY, | ||
94 | .pipe = 1, | ||
95 | .formats = sun4i_backend_layer_formats_overlay, | ||
96 | .nformats = ARRAY_SIZE(sun4i_backend_layer_formats_overlay), | ||
97 | }, | ||
72 | }; | 98 | }; |
73 | 99 | ||
74 | static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, | 100 | static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, |
75 | enum drm_plane_type type) | 101 | const struct sun4i_plane_desc *plane) |
76 | { | 102 | { |
77 | struct sun4i_drv *drv = drm->dev_private; | 103 | struct sun4i_drv *drv = drm->dev_private; |
78 | struct sun4i_layer *layer; | 104 | struct sun4i_layer *layer; |
@@ -84,10 +110,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, | |||
84 | 110 | ||
85 | ret = drm_universal_plane_init(drm, &layer->plane, BIT(0), | 111 | ret = drm_universal_plane_init(drm, &layer->plane, BIT(0), |
86 | &sun4i_backend_layer_funcs, | 112 | &sun4i_backend_layer_funcs, |
87 | sun4i_backend_layer_formats, | 113 | plane->formats, plane->nformats, |
88 | ARRAY_SIZE(sun4i_backend_layer_formats), | 114 | plane->type, NULL); |
89 | type, | ||
90 | NULL); | ||
91 | if (ret) { | 115 | if (ret) { |
92 | dev_err(drm->dev, "Couldn't initialize layer\n"); | 116 | dev_err(drm->dev, "Couldn't initialize layer\n"); |
93 | return ERR_PTR(ret); | 117 | return ERR_PTR(ret); |
@@ -97,7 +121,7 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, | |||
97 | &sun4i_backend_layer_helper_funcs); | 121 | &sun4i_backend_layer_helper_funcs); |
98 | layer->drv = drv; | 122 | layer->drv = drv; |
99 | 123 | ||
100 | if (type == DRM_PLANE_TYPE_PRIMARY) | 124 | if (plane->type == DRM_PLANE_TYPE_PRIMARY) |
101 | drv->primary = &layer->plane; | 125 | drv->primary = &layer->plane; |
102 | 126 | ||
103 | return layer; | 127 | return layer; |
@@ -109,8 +133,8 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) | |||
109 | struct sun4i_layer **layers; | 133 | struct sun4i_layer **layers; |
110 | int i; | 134 | int i; |
111 | 135 | ||
112 | layers = devm_kcalloc(drm->dev, SUN4I_NUM_LAYERS, sizeof(**layers), | 136 | layers = devm_kcalloc(drm->dev, ARRAY_SIZE(sun4i_backend_planes), |
113 | GFP_KERNEL); | 137 | sizeof(**layers), GFP_KERNEL); |
114 | if (!layers) | 138 | if (!layers) |
115 | return ERR_PTR(-ENOMEM); | 139 | return ERR_PTR(-ENOMEM); |
116 | 140 | ||
@@ -135,13 +159,11 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) | |||
135 | * SoCs that support it, sprites could fill the need for more | 159 | * SoCs that support it, sprites could fill the need for more |
136 | * layers. | 160 | * layers. |
137 | */ | 161 | */ |
138 | for (i = 0; i < SUN4I_NUM_LAYERS; i++) { | 162 | for (i = 0; i < ARRAY_SIZE(sun4i_backend_planes); i++) { |
139 | enum drm_plane_type type = (i == 0) | 163 | const struct sun4i_plane_desc *plane = &sun4i_backend_planes[i]; |
140 | ? DRM_PLANE_TYPE_PRIMARY | ||
141 | : DRM_PLANE_TYPE_OVERLAY; | ||
142 | struct sun4i_layer *layer = layers[i]; | 164 | struct sun4i_layer *layer = layers[i]; |
143 | 165 | ||
144 | layer = sun4i_layer_init_one(drm, type); | 166 | layer = sun4i_layer_init_one(drm, plane); |
145 | if (IS_ERR(layer)) { | 167 | if (IS_ERR(layer)) { |
146 | dev_err(drm->dev, "Couldn't initialize %s plane\n", | 168 | dev_err(drm->dev, "Couldn't initialize %s plane\n", |
147 | i ? "overlay" : "primary"); | 169 | i ? "overlay" : "primary"); |
@@ -149,10 +171,10 @@ struct sun4i_layer **sun4i_layers_init(struct drm_device *drm) | |||
149 | }; | 171 | }; |
150 | 172 | ||
151 | DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n", | 173 | DRM_DEBUG_DRIVER("Assigning %s plane to pipe %d\n", |
152 | i ? "overlay" : "primary", i); | 174 | i ? "overlay" : "primary", plane->pipe); |
153 | regmap_update_bits(drv->backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i), | 175 | regmap_update_bits(drv->backend->regs, SUN4I_BACKEND_ATTCTL_REG0(i), |
154 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK, | 176 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL_MASK, |
155 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(i)); | 177 | SUN4I_BACKEND_ATTCTL_REG0_LAY_PIPESEL(plane->pipe)); |
156 | 178 | ||
157 | layer->id = i; | 179 | layer->id = i; |
158 | }; | 180 | }; |
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index b84147896294..1dd3d9eabf2e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c | |||
@@ -161,10 +161,10 @@ struct tv_mode { | |||
161 | bool dac3_en; | 161 | bool dac3_en; |
162 | bool dac_bit25_en; | 162 | bool dac_bit25_en; |
163 | 163 | ||
164 | struct color_gains *color_gains; | 164 | const struct color_gains *color_gains; |
165 | struct burst_levels *burst_levels; | 165 | const struct burst_levels *burst_levels; |
166 | struct video_levels *video_levels; | 166 | const struct video_levels *video_levels; |
167 | struct resync_parameters *resync_params; | 167 | const struct resync_parameters *resync_params; |
168 | }; | 168 | }; |
169 | 169 | ||
170 | struct sun4i_tv { | 170 | struct sun4i_tv { |
@@ -178,39 +178,39 @@ struct sun4i_tv { | |||
178 | struct sun4i_drv *drv; | 178 | struct sun4i_drv *drv; |
179 | }; | 179 | }; |
180 | 180 | ||
181 | struct video_levels ntsc_video_levels = { | 181 | static const struct video_levels ntsc_video_levels = { |
182 | .black = 282, .blank = 240, | 182 | .black = 282, .blank = 240, |
183 | }; | 183 | }; |
184 | 184 | ||
185 | struct video_levels pal_video_levels = { | 185 | static const struct video_levels pal_video_levels = { |
186 | .black = 252, .blank = 252, | 186 | .black = 252, .blank = 252, |
187 | }; | 187 | }; |
188 | 188 | ||
189 | struct burst_levels ntsc_burst_levels = { | 189 | static const struct burst_levels ntsc_burst_levels = { |
190 | .cb = 79, .cr = 0, | 190 | .cb = 79, .cr = 0, |
191 | }; | 191 | }; |
192 | 192 | ||
193 | struct burst_levels pal_burst_levels = { | 193 | static const struct burst_levels pal_burst_levels = { |
194 | .cb = 40, .cr = 40, | 194 | .cb = 40, .cr = 40, |
195 | }; | 195 | }; |
196 | 196 | ||
197 | struct color_gains ntsc_color_gains = { | 197 | static const struct color_gains ntsc_color_gains = { |
198 | .cb = 160, .cr = 160, | 198 | .cb = 160, .cr = 160, |
199 | }; | 199 | }; |
200 | 200 | ||
201 | struct color_gains pal_color_gains = { | 201 | static const struct color_gains pal_color_gains = { |
202 | .cb = 224, .cr = 224, | 202 | .cb = 224, .cr = 224, |
203 | }; | 203 | }; |
204 | 204 | ||
205 | struct resync_parameters ntsc_resync_parameters = { | 205 | static const struct resync_parameters ntsc_resync_parameters = { |
206 | .field = false, .line = 14, .pixel = 12, | 206 | .field = false, .line = 14, .pixel = 12, |
207 | }; | 207 | }; |
208 | 208 | ||
209 | struct resync_parameters pal_resync_parameters = { | 209 | static const struct resync_parameters pal_resync_parameters = { |
210 | .field = true, .line = 13, .pixel = 12, | 210 | .field = true, .line = 13, .pixel = 12, |
211 | }; | 211 | }; |
212 | 212 | ||
213 | struct tv_mode tv_modes[] = { | 213 | static const struct tv_mode tv_modes[] = { |
214 | { | 214 | { |
215 | .name = "NTSC", | 215 | .name = "NTSC", |
216 | .mode = SUN4I_TVE_CFG0_RES_480i, | 216 | .mode = SUN4I_TVE_CFG0_RES_480i, |
@@ -289,13 +289,13 @@ drm_connector_to_sun4i_tv(struct drm_connector *connector) | |||
289 | * So far, it doesn't seem to be preserved when the mode is passed by | 289 | * So far, it doesn't seem to be preserved when the mode is passed by |
290 | * to mode_set for some reason. | 290 | * to mode_set for some reason. |
291 | */ | 291 | */ |
292 | static struct tv_mode *sun4i_tv_find_tv_by_mode(struct drm_display_mode *mode) | 292 | static const struct tv_mode *sun4i_tv_find_tv_by_mode(const struct drm_display_mode *mode) |
293 | { | 293 | { |
294 | int i; | 294 | int i; |
295 | 295 | ||
296 | /* First try to identify the mode by name */ | 296 | /* First try to identify the mode by name */ |
297 | for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { | 297 | for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { |
298 | struct tv_mode *tv_mode = &tv_modes[i]; | 298 | const struct tv_mode *tv_mode = &tv_modes[i]; |
299 | 299 | ||
300 | DRM_DEBUG_DRIVER("Comparing mode %s vs %s", | 300 | DRM_DEBUG_DRIVER("Comparing mode %s vs %s", |
301 | mode->name, tv_mode->name); | 301 | mode->name, tv_mode->name); |
@@ -306,7 +306,7 @@ static struct tv_mode *sun4i_tv_find_tv_by_mode(struct drm_display_mode *mode) | |||
306 | 306 | ||
307 | /* Then by number of lines */ | 307 | /* Then by number of lines */ |
308 | for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { | 308 | for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { |
309 | struct tv_mode *tv_mode = &tv_modes[i]; | 309 | const struct tv_mode *tv_mode = &tv_modes[i]; |
310 | 310 | ||
311 | DRM_DEBUG_DRIVER("Comparing mode %s vs %s (X: %d vs %d)", | 311 | DRM_DEBUG_DRIVER("Comparing mode %s vs %s (X: %d vs %d)", |
312 | mode->name, tv_mode->name, | 312 | mode->name, tv_mode->name, |
@@ -319,7 +319,7 @@ static struct tv_mode *sun4i_tv_find_tv_by_mode(struct drm_display_mode *mode) | |||
319 | return NULL; | 319 | return NULL; |
320 | } | 320 | } |
321 | 321 | ||
322 | static void sun4i_tv_mode_to_drm_mode(struct tv_mode *tv_mode, | 322 | static void sun4i_tv_mode_to_drm_mode(const struct tv_mode *tv_mode, |
323 | struct drm_display_mode *mode) | 323 | struct drm_display_mode *mode) |
324 | { | 324 | { |
325 | DRM_DEBUG_DRIVER("Creating mode %s\n", mode->name); | 325 | DRM_DEBUG_DRIVER("Creating mode %s\n", mode->name); |
@@ -386,7 +386,7 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder, | |||
386 | struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); | 386 | struct sun4i_tv *tv = drm_encoder_to_sun4i_tv(encoder); |
387 | struct sun4i_drv *drv = tv->drv; | 387 | struct sun4i_drv *drv = tv->drv; |
388 | struct sun4i_tcon *tcon = drv->tcon; | 388 | struct sun4i_tcon *tcon = drv->tcon; |
389 | struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode); | 389 | const struct tv_mode *tv_mode = sun4i_tv_find_tv_by_mode(mode); |
390 | 390 | ||
391 | sun4i_tcon1_mode_set(tcon, mode); | 391 | sun4i_tcon1_mode_set(tcon, mode); |
392 | 392 | ||
@@ -507,8 +507,14 @@ static int sun4i_tv_comp_get_modes(struct drm_connector *connector) | |||
507 | int i; | 507 | int i; |
508 | 508 | ||
509 | for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { | 509 | for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { |
510 | struct drm_display_mode *mode = drm_mode_create(connector->dev); | 510 | struct drm_display_mode *mode; |
511 | struct tv_mode *tv_mode = &tv_modes[i]; | 511 | const struct tv_mode *tv_mode = &tv_modes[i]; |
512 | |||
513 | mode = drm_mode_create(connector->dev); | ||
514 | if (!mode) { | ||
515 | DRM_ERROR("Failed to create a new display mode\n"); | ||
516 | return 0; | ||
517 | } | ||
512 | 518 | ||
513 | strcpy(mode->name, tv_mode->name); | 519 | strcpy(mode->name, tv_mode->name); |
514 | 520 | ||