diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/xilinxfb.c | 133 |
1 files changed, 80 insertions, 53 deletions
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 9aa754a25218..12d91279996d 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c | |||
@@ -196,23 +196,17 @@ static struct fb_ops xilinxfb_ops = | |||
196 | .fb_imageblit = cfb_imageblit, | 196 | .fb_imageblit = cfb_imageblit, |
197 | }; | 197 | }; |
198 | 198 | ||
199 | /* === The device driver === */ | 199 | /* --------------------------------------------------------------------- |
200 | * Bus independent setup/teardown | ||
201 | */ | ||
200 | 202 | ||
201 | static int | 203 | static int xilinxfb_assign(struct device *dev, unsigned long physaddr, |
202 | xilinxfb_drv_probe(struct device *dev) | 204 | int width_mm, int height_mm, int rotate) |
203 | { | 205 | { |
204 | struct platform_device *pdev; | ||
205 | struct xilinxfb_platform_data *pdata; | ||
206 | struct xilinxfb_drvdata *drvdata; | 206 | struct xilinxfb_drvdata *drvdata; |
207 | struct resource *regs_res; | 207 | int rc; |
208 | int retval; | ||
209 | |||
210 | if (!dev) | ||
211 | return -EINVAL; | ||
212 | |||
213 | pdev = to_platform_device(dev); | ||
214 | pdata = pdev->dev.platform_data; | ||
215 | 208 | ||
209 | /* Allocate the driver data region */ | ||
216 | drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); | 210 | drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); |
217 | if (!drvdata) { | 211 | if (!drvdata) { |
218 | dev_err(dev, "Couldn't allocate device private record\n"); | 212 | dev_err(dev, "Couldn't allocate device private record\n"); |
@@ -221,40 +215,39 @@ xilinxfb_drv_probe(struct device *dev) | |||
221 | dev_set_drvdata(dev, drvdata); | 215 | dev_set_drvdata(dev, drvdata); |
222 | 216 | ||
223 | /* Map the control registers in */ | 217 | /* Map the control registers in */ |
224 | regs_res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 218 | if (!request_mem_region(physaddr, 8, DRIVER_NAME)) { |
225 | if (!regs_res || (regs_res->end - regs_res->start + 1 < 8)) { | 219 | dev_err(dev, "Couldn't lock memory region at 0x%08lX\n", |
226 | dev_err(dev, "Couldn't get registers resource\n"); | 220 | physaddr); |
227 | retval = -EFAULT; | 221 | rc = -ENODEV; |
228 | goto err_region; | 222 | goto err_region; |
229 | } | 223 | } |
230 | 224 | drvdata->regs_phys = physaddr; | |
231 | if (!request_mem_region(regs_res->start, 8, DRIVER_NAME)) { | 225 | drvdata->regs = ioremap(physaddr, 8); |
232 | dev_err(dev, "Couldn't lock memory region at 0x%08X\n", | 226 | if (!drvdata->regs) { |
233 | regs_res->start); | 227 | dev_err(dev, "Couldn't lock memory region at 0x%08lX\n", |
234 | retval = -EBUSY; | 228 | physaddr); |
235 | goto err_region; | 229 | rc = -ENODEV; |
230 | goto err_map; | ||
236 | } | 231 | } |
237 | drvdata->regs = (u32 __iomem*) ioremap(regs_res->start, 8); | ||
238 | drvdata->regs_phys = regs_res->start; | ||
239 | 232 | ||
240 | /* Allocate the framebuffer memory */ | 233 | /* Allocate the framebuffer memory */ |
241 | drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(FB_SIZE), | 234 | drvdata->fb_virt = dma_alloc_coherent(dev, PAGE_ALIGN(FB_SIZE), |
242 | &drvdata->fb_phys, GFP_KERNEL); | 235 | &drvdata->fb_phys, GFP_KERNEL); |
243 | if (!drvdata->fb_virt) { | 236 | if (!drvdata->fb_virt) { |
244 | dev_err(dev, "Could not allocate frame buffer memory\n"); | 237 | dev_err(dev, "Could not allocate frame buffer memory\n"); |
245 | retval = -ENOMEM; | 238 | rc = -ENOMEM; |
246 | goto err_fbmem; | 239 | goto err_fbmem; |
247 | } | 240 | } |
248 | 241 | ||
249 | /* Clear (turn to black) the framebuffer */ | 242 | /* Clear (turn to black) the framebuffer */ |
250 | memset_io((void *) drvdata->fb_virt, 0, FB_SIZE); | 243 | memset_io(drvdata->fb_virt, 0, FB_SIZE); |
251 | 244 | ||
252 | /* Tell the hardware where the frame buffer is */ | 245 | /* Tell the hardware where the frame buffer is */ |
253 | xilinx_fb_out_be32(drvdata, REG_FB_ADDR, drvdata->fb_phys); | 246 | xilinx_fb_out_be32(drvdata, REG_FB_ADDR, drvdata->fb_phys); |
254 | 247 | ||
255 | /* Turn on the display */ | 248 | /* Turn on the display */ |
256 | drvdata->reg_ctrl_default = REG_CTRL_ENABLE; | 249 | drvdata->reg_ctrl_default = REG_CTRL_ENABLE; |
257 | if (pdata && pdata->rotate_screen) | 250 | if (rotate) |
258 | drvdata->reg_ctrl_default |= REG_CTRL_ROTATE; | 251 | drvdata->reg_ctrl_default |= REG_CTRL_ROTATE; |
259 | xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default); | 252 | xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default); |
260 | 253 | ||
@@ -265,31 +258,29 @@ xilinxfb_drv_probe(struct device *dev) | |||
265 | drvdata->info.fix = xilinx_fb_fix; | 258 | drvdata->info.fix = xilinx_fb_fix; |
266 | drvdata->info.fix.smem_start = drvdata->fb_phys; | 259 | drvdata->info.fix.smem_start = drvdata->fb_phys; |
267 | drvdata->info.pseudo_palette = drvdata->pseudo_palette; | 260 | drvdata->info.pseudo_palette = drvdata->pseudo_palette; |
261 | drvdata->info.flags = FBINFO_DEFAULT; | ||
262 | drvdata->info.var = xilinx_fb_var; | ||
263 | |||
264 | xilinx_fb_var.height = height_mm; | ||
265 | xilinx_fb_var.width = width_mm; | ||
268 | 266 | ||
269 | if (fb_alloc_cmap(&drvdata->info.cmap, PALETTE_ENTRIES_NO, 0) < 0) { | 267 | /* Allocate a colour map */ |
268 | rc = fb_alloc_cmap(&drvdata->info.cmap, PALETTE_ENTRIES_NO, 0); | ||
269 | if (rc) { | ||
270 | dev_err(dev, "Fail to allocate colormap (%d entries)\n", | 270 | dev_err(dev, "Fail to allocate colormap (%d entries)\n", |
271 | PALETTE_ENTRIES_NO); | 271 | PALETTE_ENTRIES_NO); |
272 | retval = -EFAULT; | ||
273 | goto err_cmap; | 272 | goto err_cmap; |
274 | } | 273 | } |
275 | 274 | ||
276 | drvdata->info.flags = FBINFO_DEFAULT; | ||
277 | if (pdata) { | ||
278 | xilinx_fb_var.height = pdata->screen_height_mm; | ||
279 | xilinx_fb_var.width = pdata->screen_width_mm; | ||
280 | } | ||
281 | drvdata->info.var = xilinx_fb_var; | ||
282 | |||
283 | /* Register new frame buffer */ | 275 | /* Register new frame buffer */ |
284 | if (register_framebuffer(&drvdata->info) < 0) { | 276 | rc = register_framebuffer(&drvdata->info); |
277 | if (rc) { | ||
285 | dev_err(dev, "Could not register frame buffer\n"); | 278 | dev_err(dev, "Could not register frame buffer\n"); |
286 | retval = -EINVAL; | ||
287 | goto err_regfb; | 279 | goto err_regfb; |
288 | } | 280 | } |
289 | 281 | ||
290 | /* Put a banner in the log (for DEBUG) */ | 282 | /* Put a banner in the log (for DEBUG) */ |
291 | dev_dbg(dev, "regs: phys=%x, virt=%p\n", | 283 | dev_dbg(dev, "regs: phys=%lx, virt=%p\n", physaddr, drvdata->regs); |
292 | drvdata->regs_phys, drvdata->regs); | ||
293 | dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n", | 284 | dev_dbg(dev, "fb: phys=%p, virt=%p, size=%x\n", |
294 | (void*)drvdata->fb_phys, drvdata->fb_virt, FB_SIZE); | 285 | (void*)drvdata->fb_phys, drvdata->fb_virt, FB_SIZE); |
295 | return 0; /* success */ | 286 | return 0; /* success */ |
@@ -300,30 +291,25 @@ err_regfb: | |||
300 | err_cmap: | 291 | err_cmap: |
301 | dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt, | 292 | dma_free_coherent(dev, PAGE_ALIGN(FB_SIZE), drvdata->fb_virt, |
302 | drvdata->fb_phys); | 293 | drvdata->fb_phys); |
303 | |||
304 | /* Turn off the display */ | 294 | /* Turn off the display */ |
305 | xilinx_fb_out_be32(drvdata, REG_CTRL, 0); | 295 | xilinx_fb_out_be32(drvdata, REG_CTRL, 0); |
306 | iounmap(drvdata->regs); | ||
307 | 296 | ||
308 | err_fbmem: | 297 | err_fbmem: |
309 | release_mem_region(regs_res->start, 8); | 298 | iounmap(drvdata->regs); |
299 | |||
300 | err_map: | ||
301 | release_mem_region(physaddr, 8); | ||
310 | 302 | ||
311 | err_region: | 303 | err_region: |
312 | kfree(drvdata); | 304 | kfree(drvdata); |
313 | dev_set_drvdata(dev, NULL); | 305 | dev_set_drvdata(dev, NULL); |
314 | 306 | ||
315 | return retval; | 307 | return rc; |
316 | } | 308 | } |
317 | 309 | ||
318 | static int | 310 | static int xilinxfb_release(struct device *dev) |
319 | xilinxfb_drv_remove(struct device *dev) | ||
320 | { | 311 | { |
321 | struct xilinxfb_drvdata *drvdata; | 312 | struct xilinxfb_drvdata *drvdata = dev_get_drvdata(dev); |
322 | |||
323 | if (!dev) | ||
324 | return -ENODEV; | ||
325 | |||
326 | drvdata = (struct xilinxfb_drvdata *) dev_get_drvdata(dev); | ||
327 | 313 | ||
328 | #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) | 314 | #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) |
329 | xilinx_fb_blank(VESA_POWERDOWN, &drvdata->info); | 315 | xilinx_fb_blank(VESA_POWERDOWN, &drvdata->info); |
@@ -348,6 +334,47 @@ xilinxfb_drv_remove(struct device *dev) | |||
348 | return 0; | 334 | return 0; |
349 | } | 335 | } |
350 | 336 | ||
337 | /* --------------------------------------------------------------------- | ||
338 | * Platform bus binding | ||
339 | */ | ||
340 | |||
341 | static int | ||
342 | xilinxfb_drv_probe(struct device *dev) | ||
343 | { | ||
344 | struct platform_device *pdev; | ||
345 | struct xilinxfb_platform_data *pdata; | ||
346 | struct resource *res; | ||
347 | int width_mm; | ||
348 | int height_mm; | ||
349 | int rotate; | ||
350 | |||
351 | pdev = to_platform_device(dev); | ||
352 | pdata = pdev->dev.platform_data; | ||
353 | if (!pdata) { | ||
354 | dev_err(dev, "Missing pdata structure\n"); | ||
355 | return -ENODEV; | ||
356 | } | ||
357 | |||
358 | /* Find the registers address */ | ||
359 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
360 | if (!res) { | ||
361 | dev_err(dev, "Couldn't get registers resource\n"); | ||
362 | return -ENODEV; | ||
363 | } | ||
364 | |||
365 | height_mm = pdata->screen_height_mm; | ||
366 | width_mm = pdata->screen_width_mm; | ||
367 | rotate = pdata->rotate_screen ? 1 : 0; | ||
368 | |||
369 | return xilinxfb_assign(dev, res->start, width_mm, height_mm, rotate); | ||
370 | } | ||
371 | |||
372 | static int | ||
373 | xilinxfb_drv_remove(struct device *dev) | ||
374 | { | ||
375 | return xilinxfb_release(dev); | ||
376 | } | ||
377 | |||
351 | 378 | ||
352 | static struct device_driver xilinxfb_driver = { | 379 | static struct device_driver xilinxfb_driver = { |
353 | .name = DRIVER_NAME, | 380 | .name = DRIVER_NAME, |