aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/Kconfig4
-rw-r--r--drivers/video/pmagb-b-fb.c98
2 files changed, 58 insertions, 44 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 18c22ba6e656..45fe65d8d7a0 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1454,8 +1454,8 @@ config FB_PMAG_BA
1454 used mainly in the MIPS-based DECstation series. 1454 used mainly in the MIPS-based DECstation series.
1455 1455
1456config FB_PMAGB_B 1456config FB_PMAGB_B
1457 bool "PMAGB-B TURBOchannel framebuffer support" 1457 tristate "PMAGB-B TURBOchannel framebuffer support"
1458 depends on (FB = y) && TC 1458 depends on TC
1459 select FB_CFB_FILLRECT 1459 select FB_CFB_FILLRECT
1460 select FB_CFB_COPYAREA 1460 select FB_CFB_COPYAREA
1461 select FB_CFB_IMAGEBLIT 1461 select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c
index a06a064ad757..7a0ce7d5af6b 100644
--- a/drivers/video/pmagb-b-fb.c
+++ b/drivers/video/pmagb-b-fb.c
@@ -11,7 +11,7 @@
11 * Michael Engel <engel@unix-ag.org>, 11 * Michael Engel <engel@unix-ag.org>,
12 * Karsten Merker <merker@linuxtag.org> and 12 * Karsten Merker <merker@linuxtag.org> and
13 * Harald Koerfgen. 13 * Harald Koerfgen.
14 * Copyright (c) 2005 Maciej W. Rozycki 14 * Copyright (c) 2005, 2006 Maciej W. Rozycki
15 * 15 *
16 * This file is subject to the terms and conditions of the GNU General 16 * This file is subject to the terms and conditions of the GNU General
17 * Public License. See the file COPYING in the main directory of this 17 * Public License. See the file COPYING in the main directory of this
@@ -25,18 +25,16 @@
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/tc.h>
28#include <linux/types.h> 29#include <linux/types.h>
29 30
30#include <asm/io.h> 31#include <asm/io.h>
31#include <asm/system.h> 32#include <asm/system.h>
32 33
33#include <asm/dec/tc.h>
34
35#include <video/pmagb-b-fb.h> 34#include <video/pmagb-b-fb.h>
36 35
37 36
38struct pmagbbfb_par { 37struct pmagbbfb_par {
39 struct fb_info *next;
40 volatile void __iomem *mmio; 38 volatile void __iomem *mmio;
41 volatile void __iomem *smem; 39 volatile void __iomem *smem;
42 volatile u32 __iomem *sfb; 40 volatile u32 __iomem *sfb;
@@ -47,8 +45,6 @@ struct pmagbbfb_par {
47}; 45};
48 46
49 47
50static struct fb_info *root_pmagbbfb_dev;
51
52static struct fb_var_screeninfo pmagbbfb_defined __initdata = { 48static struct fb_var_screeninfo pmagbbfb_defined __initdata = {
53 .bits_per_pixel = 8, 49 .bits_per_pixel = 8,
54 .red.length = 8, 50 .red.length = 8,
@@ -190,8 +186,9 @@ static void __init pmagbbfb_osc_setup(struct fb_info *info)
190 69197, 66000, 65000, 50350, 36000, 32000, 25175 186 69197, 66000, 65000, 50350, 36000, 32000, 25175
191 }; 187 };
192 struct pmagbbfb_par *par = info->par; 188 struct pmagbbfb_par *par = info->par;
189 struct tc_bus *tbus = to_tc_dev(info->device)->bus;
193 u32 count0 = 8, count1 = 8, counttc = 16 * 256 + 8; 190 u32 count0 = 8, count1 = 8, counttc = 16 * 256 + 8;
194 u32 freq0, freq1, freqtc = get_tc_speed() / 250; 191 u32 freq0, freq1, freqtc = tc_get_speed(tbus) / 250;
195 int i, j; 192 int i, j;
196 193
197 gp0_write(par, 0); /* select Osc0 */ 194 gp0_write(par, 0); /* select Osc0 */
@@ -249,26 +246,21 @@ static void __init pmagbbfb_osc_setup(struct fb_info *info)
249}; 246};
250 247
251 248
252static int __init pmagbbfb_init_one(int slot) 249static int __init pmagbbfb_probe(struct device *dev)
253{ 250{
254 char freq0[12], freq1[12]; 251 struct tc_dev *tdev = to_tc_dev(dev);
252 resource_size_t start, len;
255 struct fb_info *info; 253 struct fb_info *info;
256 struct pmagbbfb_par *par; 254 struct pmagbbfb_par *par;
257 unsigned long base_addr; 255 char freq0[12], freq1[12];
258 u32 vid_base; 256 u32 vid_base;
259 257
260 info = framebuffer_alloc(sizeof(struct pmagbbfb_par), NULL); 258 info = framebuffer_alloc(sizeof(struct pmagbbfb_par), dev);
261 if (!info) 259 if (!info)
262 return -ENOMEM; 260 return -ENOMEM;
263 261
264 par = info->par; 262 par = info->par;
265 par->slot = slot; 263 dev_set_drvdata(dev, info);
266 claim_tc_card(par->slot);
267
268 base_addr = get_tc_base_addr(par->slot);
269
270 par->next = root_pmagbbfb_dev;
271 root_pmagbbfb_dev = info;
272 264
273 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) 265 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
274 goto err_alloc; 266 goto err_alloc;
@@ -278,16 +270,22 @@ static int __init pmagbbfb_init_one(int slot)
278 info->var = pmagbbfb_defined; 270 info->var = pmagbbfb_defined;
279 info->flags = FBINFO_DEFAULT; 271 info->flags = FBINFO_DEFAULT;
280 272
273 /* Request the I/O MEM resource. */
274 start = tdev->resource.start;
275 len = tdev->resource.end - start + 1;
276 if (!request_mem_region(start, len, dev->bus_id))
277 goto err_cmap;
278
281 /* MMIO mapping setup. */ 279 /* MMIO mapping setup. */
282 info->fix.mmio_start = base_addr; 280 info->fix.mmio_start = start;
283 par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); 281 par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len);
284 if (!par->mmio) 282 if (!par->mmio)
285 goto err_cmap; 283 goto err_resource;
286 par->sfb = par->mmio + PMAGB_B_SFB; 284 par->sfb = par->mmio + PMAGB_B_SFB;
287 par->dac = par->mmio + PMAGB_B_BT459; 285 par->dac = par->mmio + PMAGB_B_BT459;
288 286
289 /* Frame buffer mapping setup. */ 287 /* Frame buffer mapping setup. */
290 info->fix.smem_start = base_addr + PMAGB_B_FBMEM; 288 info->fix.smem_start = start + PMAGB_B_FBMEM;
291 par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len); 289 par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len);
292 if (!par->smem) 290 if (!par->smem)
293 goto err_mmio_map; 291 goto err_mmio_map;
@@ -302,13 +300,15 @@ static int __init pmagbbfb_init_one(int slot)
302 if (register_framebuffer(info) < 0) 300 if (register_framebuffer(info) < 0)
303 goto err_smem_map; 301 goto err_smem_map;
304 302
303 get_device(dev);
304
305 snprintf(freq0, sizeof(freq0), "%u.%03uMHz", 305 snprintf(freq0, sizeof(freq0), "%u.%03uMHz",
306 par->osc0 / 1000, par->osc0 % 1000); 306 par->osc0 / 1000, par->osc0 % 1000);
307 snprintf(freq1, sizeof(freq1), "%u.%03uMHz", 307 snprintf(freq1, sizeof(freq1), "%u.%03uMHz",
308 par->osc1 / 1000, par->osc1 % 1000); 308 par->osc1 / 1000, par->osc1 % 1000);
309 309
310 pr_info("fb%d: %s frame buffer device in slot %d\n", 310 pr_info("fb%d: %s frame buffer device at %s\n",
311 info->node, info->fix.id, par->slot); 311 info->node, info->fix.id, dev->bus_id);
312 pr_info("fb%d: Osc0: %s, Osc1: %s, Osc%u selected\n", 312 pr_info("fb%d: Osc0: %s, Osc1: %s, Osc%u selected\n",
313 info->node, freq0, par->osc1 ? freq1 : "disabled", 313 info->node, freq0, par->osc1 ? freq1 : "disabled",
314 par->osc1 != 0); 314 par->osc1 != 0);
@@ -322,54 +322,68 @@ err_smem_map:
322err_mmio_map: 322err_mmio_map:
323 iounmap(par->mmio); 323 iounmap(par->mmio);
324 324
325err_resource:
326 release_mem_region(start, len);
327
325err_cmap: 328err_cmap:
326 fb_dealloc_cmap(&info->cmap); 329 fb_dealloc_cmap(&info->cmap);
327 330
328err_alloc: 331err_alloc:
329 root_pmagbbfb_dev = par->next;
330 release_tc_card(par->slot);
331 framebuffer_release(info); 332 framebuffer_release(info);
332 return -ENXIO; 333 return -ENXIO;
333} 334}
334 335
335static void __exit pmagbbfb_exit_one(void) 336static int __exit pmagbbfb_remove(struct device *dev)
336{ 337{
337 struct fb_info *info = root_pmagbbfb_dev; 338 struct tc_dev *tdev = to_tc_dev(dev);
339 struct fb_info *info = dev_get_drvdata(dev);
338 struct pmagbbfb_par *par = info->par; 340 struct pmagbbfb_par *par = info->par;
341 resource_size_t start, len;
339 342
343 put_device(dev);
340 unregister_framebuffer(info); 344 unregister_framebuffer(info);
341 iounmap(par->smem); 345 iounmap(par->smem);
342 iounmap(par->mmio); 346 iounmap(par->mmio);
347 start = tdev->resource.start;
348 len = tdev->resource.end - start + 1;
349 release_mem_region(start, len);
343 fb_dealloc_cmap(&info->cmap); 350 fb_dealloc_cmap(&info->cmap);
344 root_pmagbbfb_dev = par->next;
345 release_tc_card(par->slot);
346 framebuffer_release(info); 351 framebuffer_release(info);
352 return 0;
347} 353}
348 354
349 355
350/* 356/*
351 * Initialise the framebuffer. 357 * Initialize the framebuffer.
352 */ 358 */
359static const struct tc_device_id pmagbbfb_tc_table[] = {
360 { "DEC ", "PMAGB-BA" },
361 { }
362};
363MODULE_DEVICE_TABLE(tc, pmagbbfb_tc_table);
364
365static struct tc_driver pmagbbfb_driver = {
366 .id_table = pmagbbfb_tc_table,
367 .driver = {
368 .name = "pmagbbfb",
369 .bus = &tc_bus_type,
370 .probe = pmagbbfb_probe,
371 .remove = __exit_p(pmagbbfb_remove),
372 },
373};
374
353static int __init pmagbbfb_init(void) 375static int __init pmagbbfb_init(void)
354{ 376{
355 int count = 0; 377#ifndef MODULE
356 int slot;
357
358 if (fb_get_options("pmagbbfb", NULL)) 378 if (fb_get_options("pmagbbfb", NULL))
359 return -ENXIO; 379 return -ENXIO;
360 380#endif
361 while ((slot = search_tc_card("PMAGB-BA")) >= 0) { 381 return tc_register_driver(&pmagbbfb_driver);
362 if (pmagbbfb_init_one(slot) < 0)
363 break;
364 count++;
365 }
366 return (count > 0) ? 0 : -ENXIO;
367} 382}
368 383
369static void __exit pmagbbfb_exit(void) 384static void __exit pmagbbfb_exit(void)
370{ 385{
371 while (root_pmagbbfb_dev) 386 tc_unregister_driver(&pmagbbfb_driver);
372 pmagbbfb_exit_one();
373} 387}
374 388
375 389