From c3635c78e500a52c9fcd55de381a72928d9e054d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 26 Mar 2010 16:44:01 -0700 Subject: DMAENGINE: generic slave control v2 Convert the device_terminate_all() operation on the DMA engine to a generic device_control() operation which can now optionally support also pausing and resuming DMA on a certain channel. Implemented for the COH 901 318 DMAC as an example. [dan.j.williams@intel.com: update for timberdale] Signed-off-by: Linus Walleij Acked-by: Mark Brown Cc: Maciej Sosnowski Cc: Nicolas Ferre Cc: Pavel Machek Cc: Li Yang Cc: Guennadi Liakhovetski Cc: Paul Mundt Cc: Ralf Baechle Cc: Haavard Skinnemoen Cc: Magnus Damm Cc: Liam Girdwood Cc: Joe Perches Cc: Roland Dreier Signed-off-by: Dan Williams --- drivers/video/mx3fb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 772ba3f45e6f..3aa50bc276eb 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -387,7 +387,8 @@ static void sdc_disable_channel(struct mx3fb_info *mx3_fbi) spin_unlock_irqrestore(&mx3fb->lock, flags); - mx3_fbi->txd->chan->device->device_terminate_all(mx3_fbi->txd->chan); + mx3_fbi->txd->chan->device->device_control(mx3_fbi->txd->chan, + DMA_TERMINATE_ALL); mx3_fbi->txd = NULL; mx3_fbi->cookie = -EINVAL; } -- cgit v1.2.3 From 109771a68bedda77606500dc14455eca92df6769 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 19 May 2009 17:12:58 +0800 Subject: viafb: Fix various resource leaks during module_init() The current code executed from module_init() in viafb does not have proper error checking and [partial] resoure release paths in case an error happens half way through driver initialization. This patch adresses the most obvious of those issues, such as a leftover i2c bus if module_init (and thus module load) fails. [jc: fixed merge conflicts] [jc: also restored -ENOMEM return on ioremap() fail] Cc: Florian Tobias Schandinat Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Signed-off-by: Harald Welte --- drivers/video/via/viafbdev.c | 52 +++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 13 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index ce7783b63f6a..b7018ef69778 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -1,5 +1,5 @@ /* - * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. + * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. * This program is free software; you can redistribute it and/or @@ -1737,6 +1737,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, u32 default_xres, default_yres; struct VideoModeTable *vmode_entry; struct fb_var_screeninfo default_var; + int rc; u32 viafb_par_length; DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); @@ -1751,7 +1752,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, &pdev->dev); if (!viafbinfo) { printk(KERN_ERR"Could not allocate memory for viafb_info.\n"); - return -ENODEV; + return -ENOMEM; } viaparinfo = (struct viafb_par *)viafbinfo->par; @@ -1774,7 +1775,9 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, viafb_dual_fb = 0; /* Set up I2C bus stuff */ - viafb_create_i2c_bus(viaparinfo); + rc = viafb_create_i2c_bus(viaparinfo); + if (rc) + goto out_fb_release; viafb_init_chip_info(pdev, ent); viaparinfo->fbmem = pci_resource_start(pdev, 0); @@ -1785,7 +1788,8 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, viaparinfo->memsize); if (!viafbinfo->screen_base) { printk(KERN_INFO "ioremap failed\n"); - return -ENOMEM; + rc = -ENOMEM; + goto out_delete_i2c; } viafbinfo->fix.mmio_start = pci_resource_start(pdev, 1); @@ -1861,8 +1865,8 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, if (!viafbinfo1) { printk(KERN_ERR "allocate the second framebuffer struct error\n"); - framebuffer_release(viafbinfo); - return -ENOMEM; + rc = -ENOMEM; + goto out_delete_i2c; } viaparinfo1 = viafbinfo1->par; memcpy(viaparinfo1, viaparinfo, viafb_par_length); @@ -1913,21 +1917,26 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, viaparinfo->depth = fb_get_color_depth(&viafbinfo->var, &viafbinfo->fix); default_var.activate = FB_ACTIVATE_NOW; - fb_alloc_cmap(&viafbinfo->cmap, 256, 0); + rc = fb_alloc_cmap(&viafbinfo->cmap, 256, 0); + if (rc) + goto out_fb1_release; if (viafb_dual_fb && (viafb_primary_dev == LCD_Device) && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) { - if (register_framebuffer(viafbinfo1) < 0) - return -EINVAL; + rc = register_framebuffer(viafbinfo1); + if (rc) + goto out_dealloc_cmap; } - if (register_framebuffer(viafbinfo) < 0) - return -EINVAL; + rc = register_framebuffer(viafbinfo); + if (rc) + goto out_fb1_unreg_lcd_cle266; if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device) || (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266))) { - if (register_framebuffer(viafbinfo1) < 0) - return -EINVAL; + rc = register_framebuffer(viafbinfo1); + if (rc) + goto out_fb_unreg; } DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n", viafbinfo->node, viafbinfo->fix.id, default_var.xres, @@ -1936,6 +1945,23 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, viafb_init_proc(&viaparinfo->shared->proc_entry); viafb_init_dac(IGA2); return 0; + +out_fb_unreg: + unregister_framebuffer(viafbinfo); +out_fb1_unreg_lcd_cle266: + if (viafb_dual_fb && (viafb_primary_dev == LCD_Device) + && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) + unregister_framebuffer(viafbinfo1); +out_dealloc_cmap: + fb_dealloc_cmap(&viafbinfo->cmap); +out_fb1_release: + if (viafbinfo1) + framebuffer_release(viafbinfo1); +out_delete_i2c: + viafb_delete_i2c_buss(viaparinfo); +out_fb_release: + framebuffer_release(viafbinfo); + return rc; } static void __devexit via_pci_remove(struct pci_dev *pdev) -- cgit v1.2.3 From b72a5070c74f5ca9a45a03c2d625daab66d0a820 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 19 May 2009 15:50:58 +0800 Subject: viafb: use proper pci config API This patch alters viafb to use the proper Linux in-kernel API to access PCI configuration space, rather than poking at I/O ports by itself. Cc: Florian Tobias Schandinat Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Signed-off-by: Harald Welte --- drivers/video/via/hw.c | 62 +++++++++++++++++++++++++++----------------- drivers/video/via/hw.h | 4 +-- drivers/video/via/viafbdev.c | 4 +++ 3 files changed, 44 insertions(+), 26 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index f2583b1b527f..c94bcce71eaf 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -2473,24 +2473,37 @@ static void disable_second_display_channel(void) viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6); } +static u_int16_t via_function3[] = { + CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3, + CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3, + P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, +}; + +/* Get the BIOS-configured framebuffer size from PCI configuration space + * of function 3 in the respective chipset */ int viafb_get_fb_size_from_pci(void) { - unsigned long configid, deviceid, FBSize = 0; - int VideoMemSize; - int DeviceFound = false; - - for (configid = 0x80000000; configid < 0x80010800; configid += 0x100) { - outl(configid, (unsigned long)0xCF8); - deviceid = (inl((unsigned long)0xCFC) >> 16) & 0xffff; - - switch (deviceid) { - case CLE266: - case KM400: - outl(configid + 0xE0, (unsigned long)0xCF8); - FBSize = inl((unsigned long)0xCFC); - DeviceFound = true; /* Found device id */ - break; + int i; + u_int8_t offset = 0; + u_int32_t FBSize; + u_int32_t VideoMemSize; + + /* search for the "FUNCTION3" device in this chipset */ + for (i = 0; i < ARRAY_SIZE(via_function3); i++) { + struct pci_dev *pdev; + + pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i], + NULL); + if (!pdev) + continue; + + DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device); + switch (pdev->device) { + case CLE266_FUNCTION3: + case KM400_FUNCTION3: + offset = 0xE0; + break; case CN400_FUNCTION3: case CN700_FUNCTION3: case CX700_FUNCTION3: @@ -2500,21 +2513,22 @@ int viafb_get_fb_size_from_pci(void) case P4M900_FUNCTION3: case VX800_FUNCTION3: case VX855_FUNCTION3: - /*case CN750_FUNCTION3: */ - outl(configid + 0xA0, (unsigned long)0xCF8); - FBSize = inl((unsigned long)0xCFC); - DeviceFound = true; /* Found device id */ - break; - - default: + /*case CN750_FUNCTION3: */ + offset = 0xA0; break; } - if (DeviceFound) + if (!offset) break; + + pci_read_config_dword(pdev, offset, &FBSize); + pci_dev_put(pdev); } - DEBUG_MSG(KERN_INFO "Device ID = %lx\n", deviceid); + if (!offset) { + printk(KERN_ERR "cannot determine framebuffer size\n"); + return -EIO; + } FBSize = FBSize & 0x00007000; DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize); diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index 12ef32d334cb..d6b25acd4a99 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -823,8 +823,8 @@ struct iga2_crtc_timing { }; /* device ID */ -#define CLE266 0x3123 -#define KM400 0x3205 +#define CLE266_FUNCTION3 0x3123 +#define KM400_FUNCTION3 0x3205 #define CN400_FUNCTION2 0x2259 #define CN400_FUNCTION3 0x3259 /* support VT3314 chipset */ diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index b7018ef69778..8af405bf077b 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -1782,6 +1782,10 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, viafb_init_chip_info(pdev, ent); viaparinfo->fbmem = pci_resource_start(pdev, 0); viaparinfo->memsize = viafb_get_fb_size_from_pci(); + if (viaparinfo->memsize < 0) { + rc = viaparinfo->memsize; + goto out_delete_i2c; + } viaparinfo->fbmem_free = viaparinfo->memsize; viaparinfo->fbmem_used = 0; viafbinfo->screen_base = ioremap_nocache(viaparinfo->fbmem, -- cgit v1.2.3 From 1b1f8cd299d3c5a90c2ec1c24c271a0b536e5891 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 26 Mar 2010 15:45:39 -0600 Subject: viafb: Unmap the frame buffer on initialization error This was part of Harald's "make viafb a first-class citizen using pci_driver" patch, but somehow got dropped when that patch went into mainline. Cc: Florian Tobias Schandinat Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Signed-off-by: Jonathan Corbet --- drivers/video/via/viafbdev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 8af405bf077b..8955ab4caac8 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -1870,7 +1870,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, printk(KERN_ERR "allocate the second framebuffer struct error\n"); rc = -ENOMEM; - goto out_delete_i2c; + goto out_unmap_screen; } viaparinfo1 = viafbinfo1->par; memcpy(viaparinfo1, viaparinfo, viafb_par_length); @@ -1961,6 +1961,8 @@ out_dealloc_cmap: out_fb1_release: if (viafbinfo1) framebuffer_release(viafbinfo1); +out_unmap_screen: + iounmap(viafbinfo->screen_base); out_delete_i2c: viafb_delete_i2c_buss(viaparinfo); out_fb_release: -- cgit v1.2.3 From 9ca43cf41d014e12f4b25d4538f362d7513448dd Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Sat, 27 Mar 2010 12:14:52 -0600 Subject: viafb: Retain GEMODE reserved bits Commit c3e25673843153ea75fda79a47cf12f10a25ca37 (viafb: 2D engine rewrite) changed the setting of the GEMODE register so that the reserved bits are no longer preserved. Fix that; at the same time, move this code to its own function and restore the use of symbolic constants. Cc: Florian Tobias Schandinat Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Signed-off-by: Jonathan Corbet --- drivers/video/via/accel.c | 49 +++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index d5077dfa9e00..a52147cf7f09 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -165,12 +165,42 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, return 0; } +/* + * Figure out an appropriate bytes-per-pixel setting. + */ +static int viafb_set_bpp(void __iomem *engine, u8 bpp) +{ + u32 gemode; + + /* Preserve the reserved bits */ + /* Lowest 2 bits to zero gives us no rotation */ + gemode = readl(engine + VIA_REG_GEMODE) & 0xfffffcfc; + switch (bpp) { + case 8: + gemode |= VIA_GEM_8bpp; + break; + case 16: + gemode |= VIA_GEM_16bpp; + break; + case 32: + gemode |= VIA_GEM_32bpp; + break; + default: + printk(KERN_WARNING "hw_bitblt_2: Unsupported bpp %d\n", bpp); + return -EINVAL; + } + writel(gemode, engine + VIA_REG_GEMODE); + return 0; +} + + static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height, u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y, u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y, u32 fg_color, u32 bg_color, u8 fill_rop) { u32 ge_cmd = 0, tmp, i; + int ret; if (!op || op > 3) { printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op); @@ -204,22 +234,9 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height, } } - switch (dst_bpp) { - case 8: - tmp = 0x00000000; - break; - case 16: - tmp = 0x00000100; - break; - case 32: - tmp = 0x00000300; - break; - default: - printk(KERN_WARNING "hw_bitblt_2: Unsupported bpp %d\n", - dst_bpp); - return -EINVAL; - } - writel(tmp, engine + 0x04); + ret = viafb_set_bpp(engine, dst_bpp); + if (ret) + return ret; if (op == VIA_BITBLT_FILL) tmp = 0; -- cgit v1.2.3 From f1b99aa9dbe908b2839885aa999d6e8512fe1040 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 9 Apr 2010 14:06:16 -0600 Subject: viafb: Unify duplicated set_bpp() code As suggested by Florian: make both mode-setting paths use the same code. Cc: Florian Tobias Schandinat Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Signed-off-by: Jonathan Corbet --- drivers/video/via/accel.c | 78 ++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 45 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index a52147cf7f09..7c1d9c41623d 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -20,12 +20,42 @@ */ #include "global.h" +/* + * Figure out an appropriate bytes-per-pixel setting. + */ +static int viafb_set_bpp(void __iomem *engine, u8 bpp) +{ + u32 gemode; + + /* Preserve the reserved bits */ + /* Lowest 2 bits to zero gives us no rotation */ + gemode = readl(engine + VIA_REG_GEMODE) & 0xfffffcfc; + switch (bpp) { + case 8: + gemode |= VIA_GEM_8bpp; + break; + case 16: + gemode |= VIA_GEM_16bpp; + break; + case 32: + gemode |= VIA_GEM_32bpp; + break; + default: + printk(KERN_WARNING "viafb_set_bpp: Unsupported bpp %d\n", bpp); + return -EINVAL; + } + writel(gemode, engine + VIA_REG_GEMODE); + return 0; +} + + static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y, u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y, u32 fg_color, u32 bg_color, u8 fill_rop) { u32 ge_cmd = 0, tmp, i; + int ret; if (!op || op > 3) { printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op); @@ -59,22 +89,9 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, } } - switch (dst_bpp) { - case 8: - tmp = 0x00000000; - break; - case 16: - tmp = 0x00000100; - break; - case 32: - tmp = 0x00000300; - break; - default: - printk(KERN_WARNING "hw_bitblt_1: Unsupported bpp %d\n", - dst_bpp); - return -EINVAL; - } - writel(tmp, engine + 0x04); + ret = viafb_set_bpp(engine, dst_bpp); + if (ret) + return ret; if (op != VIA_BITBLT_FILL) { if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000) @@ -165,35 +182,6 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, return 0; } -/* - * Figure out an appropriate bytes-per-pixel setting. - */ -static int viafb_set_bpp(void __iomem *engine, u8 bpp) -{ - u32 gemode; - - /* Preserve the reserved bits */ - /* Lowest 2 bits to zero gives us no rotation */ - gemode = readl(engine + VIA_REG_GEMODE) & 0xfffffcfc; - switch (bpp) { - case 8: - gemode |= VIA_GEM_8bpp; - break; - case 16: - gemode |= VIA_GEM_16bpp; - break; - case 32: - gemode |= VIA_GEM_32bpp; - break; - default: - printk(KERN_WARNING "hw_bitblt_2: Unsupported bpp %d\n", bpp); - return -EINVAL; - } - writel(gemode, engine + VIA_REG_GEMODE); - return 0; -} - - static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height, u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y, u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y, -- cgit v1.2.3 From 107ea34db4560e6db41a9da90128ccc5e60f6b21 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 20 May 2009 01:36:03 +0800 Subject: viafb: Determine type of 2D engine and store it in chip_info This will help us for the upcoming support for 2D acceleration using the M1 engine. [jc: fixed merge conflicts] Signed-off-by: Harald Welte --- drivers/video/via/chip.h | 8 ++++++++ drivers/video/via/hw.c | 15 +++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h index 8c06bd3c0b4d..d9b6e06e0700 100644 --- a/drivers/video/via/chip.h +++ b/drivers/video/via/chip.h @@ -121,9 +121,17 @@ struct lvds_chip_information { int i2c_port; }; +/* The type of 2D engine */ +enum via_2d_engine { + VIA_2D_ENG_H2, + VIA_2D_ENG_H5, + VIA_2D_ENG_M1, +}; + struct chip_information { int gfx_chip_name; int gfx_chip_revision; + enum via_2d_engine twod_engine; struct tmds_chip_information tmds_chip_info; struct lvds_chip_information lvds_chip_info; struct lvds_chip_information lvds_chip_info2; diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index c94bcce71eaf..ae664fbd7e80 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -2016,6 +2016,21 @@ static void init_gfx_chip_info(struct pci_dev *pdev, CX700_REVISION_700; } } + + /* Determine which 2D engine we have */ + switch (viaparinfo->chip_info->gfx_chip_name) { + case UNICHROME_VX800: + case UNICHROME_VX855: + viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1; + break; + case UNICHROME_K8M890: + case UNICHROME_P4M900: + viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H5; + break; + default: + viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H2; + break; + } } static void init_tmds_chip_info(void) -- cgit v1.2.3 From 1317824376482781200980c6f026ef576d7ed1dd Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Sat, 27 Mar 2010 13:08:23 -0600 Subject: viafb: complete support for VX800/VX855 accelerated framebuffer This patch is a painful merge of change a90bab567ece3e915d0ccd55ab00c9bb333fa8c0 (viafb: Add support for 2D accelerated framebuffer on VX800/VX855) in the OLPC tree, originally by Harald Welte. Harald's changelog read: The VX800/VX820 and the VX855/VX875 chipsets have a different 2D acceleration engine called "M1". The M1 engine has some subtle (and some not-so-subtle) differences to the previous engines, so support for accelerated framebuffer on those chipsets was disabled so far. This merge tries to preserve Harald's changes in the framework of the much-changed 2.6.34 viafb code. Cc: Florian Tobias Schandinat Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Signed-off-by: Jonathan Corbet --- drivers/video/via/accel.c | 42 +++++++++++++++++++++++++++++++++--------- drivers/video/via/accel.h | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 9 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index 7c1d9c41623d..0d90c859cc1c 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -317,6 +317,7 @@ int viafb_init_engine(struct fb_info *info) { struct viafb_par *viapar = info->par; void __iomem *engine; + int highest_reg, i; u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high, vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name; @@ -328,6 +329,18 @@ int viafb_init_engine(struct fb_info *info) return -ENOMEM; } + /* Initialize registers to reset the 2D engine */ + switch (viapar->shared->chip_info.twod_engine) { + case VIA_2D_ENG_M1: + highest_reg = 0x5c; + break; + default: + highest_reg = 0x40; + break; + } + for (i = 0; i <= highest_reg; i += 4) + writel(0x0, engine + i); + switch (chip_name) { case UNICHROME_CLE266: case UNICHROME_K400: @@ -357,13 +370,12 @@ int viafb_init_engine(struct fb_info *info) viapar->shared->vq_vram_addr = viapar->fbmem_free; viapar->fbmem_used += VQ_SIZE; - /* Init 2D engine reg to reset 2D engine */ - writel(0x0, engine + VIA_REG_KEYCONTROL); - /* Init AGP and VQ regs */ switch (chip_name) { case UNICHROME_K8M890: case UNICHROME_P4M900: + case UNICHROME_VX800: + case UNICHROME_VX855: writel(0x00100000, engine + VIA_REG_CR_TRANSET); writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE); writel(0x02000000, engine + VIA_REG_CR_TRANSPACE); @@ -398,6 +410,8 @@ int viafb_init_engine(struct fb_info *info) switch (chip_name) { case UNICHROME_K8M890: case UNICHROME_P4M900: + case UNICHROME_VX800: + case UNICHROME_VX855: vq_start_low |= 0x20000000; vq_end_low |= 0x20000000; vq_high |= 0x20000000; @@ -475,15 +489,25 @@ void viafb_wait_engine_idle(struct fb_info *info) { struct viafb_par *viapar = info->par; int loop = 0; + u32 mask; - while (!(readl(viapar->shared->engine_mmio + VIA_REG_STATUS) & - VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { - loop++; - cpu_relax(); + switch (viapar->shared->chip_info.twod_engine) { + case VIA_2D_ENG_H5: + case VIA_2D_ENG_M1: + mask = VIA_CMD_RGTR_BUSY_M1 | VIA_2D_ENG_BUSY_M1 | + VIA_3D_ENG_BUSY_M1; + break; + default: + while (!(readl(viapar->shared->engine_mmio + VIA_REG_STATUS) & + VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { + loop++; + cpu_relax(); + } + mask = VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY; + break; } - while ((readl(viapar->shared->engine_mmio + VIA_REG_STATUS) & - (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && + while ((readl(viapar->shared->engine_mmio + VIA_REG_STATUS) & mask) && (loop < MAXLOOP)) { loop++; cpu_relax(); diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h index 615c84ad0f01..2c122d292365 100644 --- a/drivers/video/via/accel.h +++ b/drivers/video/via/accel.h @@ -67,6 +67,34 @@ /* from 0x100 to 0x1ff */ #define VIA_REG_COLORPAT 0x100 +/* defines for VIA 2D registers for vt3353/3409 (M1 engine)*/ +#define VIA_REG_GECMD_M1 0x000 +#define VIA_REG_GEMODE_M1 0x004 +#define VIA_REG_GESTATUS_M1 0x004 /* as same as VIA_REG_GEMODE */ +#define VIA_REG_PITCH_M1 0x008 /* pitch of src and dst */ +#define VIA_REG_DIMENSION_M1 0x00C /* width and height */ +#define VIA_REG_DSTPOS_M1 0x010 +#define VIA_REG_LINE_XY_M1 0x010 +#define VIA_REG_DSTBASE_M1 0x014 +#define VIA_REG_SRCPOS_M1 0x018 +#define VIA_REG_LINE_K1K2_M1 0x018 +#define VIA_REG_SRCBASE_M1 0x01C +#define VIA_REG_PATADDR_M1 0x020 +#define VIA_REG_MONOPAT0_M1 0x024 +#define VIA_REG_MONOPAT1_M1 0x028 +#define VIA_REG_OFFSET_M1 0x02C +#define VIA_REG_LINE_ERROR_M1 0x02C +#define VIA_REG_CLIPTL_M1 0x040 /* top and left of clipping */ +#define VIA_REG_CLIPBR_M1 0x044 /* bottom and right of clipping */ +#define VIA_REG_KEYCONTROL_M1 0x048 /* color key control */ +#define VIA_REG_FGCOLOR_M1 0x04C +#define VIA_REG_DSTCOLORKEY_M1 0x04C /* as same as VIA_REG_FG */ +#define VIA_REG_BGCOLOR_M1 0x050 +#define VIA_REG_SRCCOLORKEY_M1 0x050 /* as same as VIA_REG_BG */ +#define VIA_REG_MONOPATFGC_M1 0x058 /* Add BG color of Pattern. */ +#define VIA_REG_MONOPATBGC_M1 0x05C /* Add FG color of Pattern. */ +#define VIA_REG_COLORPAT_M1 0x100 /* from 0x100 to 0x1ff */ + /* VIA_REG_PITCH(0x38): Pitch Setting */ #define VIA_PITCH_ENABLE 0x80000000 @@ -157,6 +185,18 @@ /* Virtual Queue is busy */ #define VIA_VR_QUEUE_BUSY 0x00020000 +/* VIA_REG_STATUS(0x400): Engine Status for H5 */ +#define VIA_CMD_RGTR_BUSY_H5 0x00000010 /* Command Regulator is busy */ +#define VIA_2D_ENG_BUSY_H5 0x00000002 /* 2D Engine is busy */ +#define VIA_3D_ENG_BUSY_H5 0x00001FE1 /* 3D Engine is busy */ +#define VIA_VR_QUEUE_BUSY_H5 0x00000004 /* Virtual Queue is busy */ + +/* VIA_REG_STATUS(0x400): Engine Status for VT3353/3409 */ +#define VIA_CMD_RGTR_BUSY_M1 0x00000010 /* Command Regulator is busy */ +#define VIA_2D_ENG_BUSY_M1 0x00000002 /* 2D Engine is busy */ +#define VIA_3D_ENG_BUSY_M1 0x00001FE1 /* 3D Engine is busy */ +#define VIA_VR_QUEUE_BUSY_M1 0x00000004 /* Virtual Queue is busy */ + #define MAXLOOP 0xFFFFFF #define VIA_BITBLT_COLOR 1 -- cgit v1.2.3 From c205d932530719d2a6ddb9152650e5bbe80c9400 Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Sun, 7 Jun 2009 13:59:51 -0400 Subject: viafb: Add 1200x900 DCON/LCD panel modes for OLPC XO-1.5 [jc: extensive merge conflict fixes] Cc: Florian Tobias Schandinat Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Signed-off-by: Chris Ball --- drivers/video/via/hw.c | 1 + drivers/video/via/ioctl.h | 2 +- drivers/video/via/lcd.c | 9 +++++++++ drivers/video/via/lcd.h | 2 ++ drivers/video/via/share.h | 7 +++++++ drivers/video/via/viamode.c | 14 ++++++++++++++ 6 files changed, 34 insertions(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index ae664fbd7e80..2322612fbb95 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -62,6 +62,7 @@ static struct pll_map pll_value[] = { CX700_52_977M, VX855_52_977M}, {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M, CX700_56_250M, VX855_56_250M}, + {CLK_57_275M, 0, 0, 0, VX855_57_275M}, {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M, CX700_60_466M, VX855_60_466M}, {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M, diff --git a/drivers/video/via/ioctl.h b/drivers/video/via/ioctl.h index de899807eade..c430fa23008a 100644 --- a/drivers/video/via/ioctl.h +++ b/drivers/video/via/ioctl.h @@ -75,7 +75,7 @@ /*SAMM operation flag*/ #define OP_SAMM 0x80 -#define LCD_PANEL_ID_MAXIMUM 22 +#define LCD_PANEL_ID_MAXIMUM 23 #define STATE_ON 0x1 #define STATE_OFF 0x0 diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index 1b1ccdc2d83d..09020f0b2d2a 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c @@ -398,6 +398,15 @@ static void fp_id_to_vindex(int panel_id) viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; viaparinfo->lvds_setting_info->LCDDithering = 1; break; + case 0x17: + /* OLPC XO-1.5 panel */ + viaparinfo->lvds_setting_info->lcd_panel_hres = 1200; + viaparinfo->lvds_setting_info->lcd_panel_vres = 900; + viaparinfo->lvds_setting_info->lcd_panel_id = + LCD_PANEL_IDD_1200X900; + viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; + viaparinfo->lvds_setting_info->LCDDithering = 0; + break; default: viaparinfo->lvds_setting_info->lcd_panel_hres = 800; viaparinfo->lvds_setting_info->lcd_panel_vres = 600; diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h index 071f47cf5be1..9762ec62b495 100644 --- a/drivers/video/via/lcd.h +++ b/drivers/video/via/lcd.h @@ -60,6 +60,8 @@ #define LCD_PANEL_IDB_1360X768 0x0B /* Resolution: 480x640, Channel: single, Dithering: Enable */ #define LCD_PANEL_IDC_480X640 0x0C +/* Resolution: 1200x900, Channel: single, Dithering: Disable */ +#define LCD_PANEL_IDD_1200X900 0x0D extern int viafb_LCD2_ON; diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index d55aaa7b912c..f974c7333522 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h @@ -570,6 +570,10 @@ #define M1200X720_R60_HSP NEGATIVE #define M1200X720_R60_VSP POSITIVE +/* 1200x900@60 Sync Polarity (DCON) */ +#define M1200X900_R60_HSP NEGATIVE +#define M1200X900_R60_VSP NEGATIVE + /* 1280x600@60 Sync Polarity (GTF Mode) */ #define M1280x600_R60_HSP NEGATIVE #define M1280x600_R60_VSP POSITIVE @@ -651,6 +655,7 @@ #define CLK_52_406M 52406000 #define CLK_52_977M 52977000 #define CLK_56_250M 56250000 +#define CLK_57_275M 57275000 #define CLK_60_466M 60466000 #define CLK_61_500M 61500000 #define CLK_65_000M 65000000 @@ -939,6 +944,7 @@ #define VX855_52_406M 0x00580C03 #define VX855_52_977M 0x00940C05 #define VX855_56_250M 0x009D0C05 +#define VX855_57_275M 0x009D8C85 /* Used by XO panel */ #define VX855_60_466M 0x00A90C05 #define VX855_61_500M 0x00AC0C05 #define VX855_65_000M 0x006D0C03 @@ -1065,6 +1071,7 @@ #define RES_1600X1200_60HZ_PIXCLOCK 6172 #define RES_1600X1200_75HZ_PIXCLOCK 4938 #define RES_1280X720_60HZ_PIXCLOCK 13426 +#define RES_1200X900_60HZ_PIXCLOCK 17459 #define RES_1920X1080_60HZ_PIXCLOCK 5787 #define RES_1400X1050_60HZ_PIXCLOCK 8214 #define RES_1400X1050_75HZ_PIXCLOCK 6410 diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index af50e244016c..6f3bcda8cb47 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c @@ -66,6 +66,7 @@ struct res_map_refresh res_map_refresh_tbl[] = { {1088, 612, RES_1088X612_60HZ_PIXCLOCK, 60}, {1152, 720, RES_1152X720_60HZ_PIXCLOCK, 60}, {1200, 720, RES_1200X720_60HZ_PIXCLOCK, 60}, + {1200, 900, RES_1200X900_60HZ_PIXCLOCK, 60}, {1280, 600, RES_1280X600_60HZ_PIXCLOCK, 60}, {1280, 720, RES_1280X720_50HZ_PIXCLOCK, 50}, {1280, 768, RES_1280X768_50HZ_PIXCLOCK, 50}, @@ -759,6 +760,16 @@ struct crt_mode_table CRTM1200x720[] = { {1568, 1200, 1200, 368, 1256, 128, 746, 720, 720, 26, 721, 3} } }; +/* 1200x900 (DCON) */ +struct crt_mode_table DCON1200x900[] = { + /* r_rate, vclk, hsp, vsp */ + {REFRESH_60, CLK_57_275M, M1200X900_R60_HSP, M1200X900_R60_VSP, + /* The correct htotal is 1240, but this doesn't raster on VX855. */ + /* Via suggested changing to a multiple of 16, hence 1264. */ + /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ + {1264, 1200, 1200, 64, 1211, 32, 912, 900, 900, 12, 901, 10} } +}; + /* 1280x600 (GTF) */ struct crt_mode_table CRTM1280x600[] = { /* r_rate, vclk, hsp, vsp */ @@ -937,6 +948,9 @@ struct VideoModeTable viafb_modes[] = { /* Display : 1200x720 (GTF) */ {CRTM1200x720, ARRAY_SIZE(CRTM1200x720)}, + /* Display : 1200x900 (DCON) */ + {DCON1200x900, ARRAY_SIZE(DCON1200x900)}, + /* Display : 1280x600 (GTF) */ {CRTM1280x600, ARRAY_SIZE(CRTM1280x600)}, -- cgit v1.2.3 From a63445a31a76474dd3f9e852e8bf08f81ee7437a Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Thu, 22 Apr 2010 14:00:18 -0700 Subject: drivers: video: msm: default to no It doesn't cure cancer .. Signed-off-by: Daniel Walker --- drivers/video/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 6e16244f3ed1..87f36efe46f3 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -2186,7 +2186,6 @@ config FB_MSM select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - default y config FB_MX3 tristate "MX3 Framebuffer support" -- cgit v1.2.3 From 8a3bdfe6cd841880a5d849c40f90093b3817f6e0 Mon Sep 17 00:00:00 2001 From: Thomas Gerlach Date: Fri, 23 Apr 2010 13:17:50 -0400 Subject: drivers/video/efifb.c: support framebuffer for NVIDIA 9400M in MacBook Pro 5,1 Description of patch: --------------------- This is a patch for the EFI framebuffer driver to enable the framebuffer of the NVIDIA 9400M as found in MacBook Pro (MBP) 5,1 and up. The framebuffer of the NVIDIA graphic cards are located at the following addresses in memory: 9400M: 0xC0010000 9600M GT: 0xB0030000 The patch delivered right here only provides the memory location of the framebuffer of the 9400M device. The 9600M GT is not covered. It is assumed that the 9400M is used when powered up the MBP. The information which device is currently powered and in use is stored in the 64 bytes large EFI variable "gpu-power-prefs". More specifically, byte 0x3B indicates whether 9600M GT (0x00) or 9400M (0x01) is online. The PCI bus IDs are the following: 9400M: PCI 03:00:00 9600M GT: PCI 02:00:00 The EFI variables can be easily read-out and manipulated with "rEFIt", an MBP specific bootloader tool. For more information on how handle rEFIt and EFI variables please consult "http://refit.sourceforge.net" and "http://ubuntuforums.org/archive/index.php/t-1076879.html". IMPORTANT NOTE: The information on how to activate the 9400M device given at "ubuntuforums.org" is not correct, since it states gpu-power-prefs[0x3B] = 0x00 -> 9400M (PCI 02:00:00) gpu-power-prefs[0x3B] = 0x01 -> 9600M GT (PCI 03:00:00) Actually, the assignment of the values and the PCI bus IDs are swapped. Suggestions: ------------ To cover framebuffers of both 9400M and 9600M GT, I would suggest to implement a conditional on "gpu-power-prefs". Depending on the value of byte 0x3B, the according framebuffer is selected. However, this requires kernel access to the EFI variables. [akpm@linux-foundation.org: rename optname, per Peter Jones] Signed-off-by: Thomas Gerlach Acked-by: Peter Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/efifb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 581d2dbf675a..ecf405562f5c 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -49,6 +49,7 @@ enum { M_MBP_2, /* MacBook Pro 2nd gen */ M_MBP_SR, /* MacBook Pro (Santa Rosa) */ M_MBP_4, /* MacBook Pro, 4th gen */ + M_MBP_5_1, /* MacBook Pro, 5,1th gen */ M_UNKNOWN /* placeholder */ }; @@ -70,6 +71,7 @@ static struct efifb_dmi_info { [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, + [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 }, [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } }; @@ -106,6 +108,7 @@ static struct dmi_system_id __initdata dmi_system_table[] = { EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR), EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4), + EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1), {}, }; -- cgit v1.2.3 From 277d32a36cba0b42c9c6836ff07f9b978566e95c Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 23 May 2009 00:35:39 +0800 Subject: viafb: rework the I2C support in the VIA framebuffer driver This patch changes the way how the various I2C busses are used internally inside the viafb driver: Previosuly, only a single i2c_adapter was created, even though two different hardware I2C busses are accessed: A structure member in a global variable was modified to indicate the bus to be used. Now, all existing hardware busses are registered with the i2c core, and the viafb_i2c_{read,write}byte[s]() function take the adapter number as function call parameter, rather than referring to the global structure member. [jc: even more painful merge with mainline changes ->2.6.34] [jc: painful merge with OLPC changes] Cc: Florian Tobias Schandinat Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Signed-off-by: Harald Welte Signed-off-by: Jonathan Corbet --- drivers/video/via/dvi.c | 35 ++++----- drivers/video/via/lcd.c | 19 ++--- drivers/video/via/via_i2c.c | 171 +++++++++++++++++++++++++++---------------- drivers/video/via/via_i2c.h | 43 +++++++---- drivers/video/via/viafbdev.c | 6 +- drivers/video/via/viafbdev.h | 4 +- drivers/video/via/vt1636.c | 36 +++++---- drivers/video/via/vt1636.h | 2 +- 8 files changed, 182 insertions(+), 134 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c index abe59b8c7a05..be513701e4e6 100644 --- a/drivers/video/via/dvi.c +++ b/drivers/video/via/dvi.c @@ -96,7 +96,7 @@ int viafb_tmds_trasmitter_identify(void) viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS; viaparinfo->chip_info-> tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; - viaparinfo->chip_info->tmds_chip_info.i2c_port = I2CPORTINDEX; + viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_I2C_ADAP_31; if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) { /* * Currently only support 12bits,dual edge,add 24bits mode later @@ -110,7 +110,7 @@ int viafb_tmds_trasmitter_identify(void) viaparinfo->chip_info->tmds_chip_info.i2c_port); return OK; } else { - viaparinfo->chip_info->tmds_chip_info.i2c_port = GPIOPORTINDEX; + viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_I2C_ADAP_2C; if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) { tmds_register_write(0x08, 0x3b); @@ -160,32 +160,26 @@ int viafb_tmds_trasmitter_identify(void) static void tmds_register_write(int index, u8 data) { - viaparinfo->shared->i2c_stuff.i2c_port = - viaparinfo->chip_info->tmds_chip_info.i2c_port; - - viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info. - tmds_chip_slave_addr, index, - data); + viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.i2c_port, + viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, + index, data); } static int tmds_register_read(int index) { u8 data; - viaparinfo->shared->i2c_stuff.i2c_port = - viaparinfo->chip_info->tmds_chip_info.i2c_port; - viafb_i2c_readbyte((u8) viaparinfo->chip_info-> - tmds_chip_info.tmds_chip_slave_addr, - (u8) index, &data); + viafb_i2c_readbyte(viaparinfo->chip_info->tmds_chip_info.i2c_port, + (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, + (u8) index, &data); return data; } static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) { - viaparinfo->shared->i2c_stuff.i2c_port = - viaparinfo->chip_info->tmds_chip_info.i2c_port; - viafb_i2c_readbytes((u8) viaparinfo->chip_info->tmds_chip_info. - tmds_chip_slave_addr, (u8) index, buff, buff_len); + viafb_i2c_readbytes(viaparinfo->chip_info->tmds_chip_info.i2c_port, + (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, + (u8) index, buff, buff_len); return 0; } @@ -541,9 +535,10 @@ void viafb_dvi_enable(void) else data = 0x37; viafb_i2c_writebyte(viaparinfo->chip_info-> - tmds_chip_info. - tmds_chip_slave_addr, - 0x08, data); + tmds_chip_info.i2c_port, + viaparinfo->chip_info-> + tmds_chip_info.tmds_chip_slave_addr, + 0x08, data); } } } diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index 09020f0b2d2a..e19441d9e49f 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c @@ -172,18 +172,16 @@ static bool lvds_identify_integratedlvds(void) int viafb_lvds_trasmitter_identify(void) { - viaparinfo->shared->i2c_stuff.i2c_port = I2CPORTINDEX; - if (viafb_lvds_identify_vt1636()) { - viaparinfo->chip_info->lvds_chip_info.i2c_port = I2CPORTINDEX; + if (viafb_lvds_identify_vt1636(VIA_I2C_ADAP_31)) { + viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_I2C_ADAP_31; DEBUG_MSG(KERN_INFO - "Found VIA VT1636 LVDS on port i2c 0x31 \n"); + "Found VIA VT1636 LVDS on port i2c 0x31\n"); } else { - viaparinfo->shared->i2c_stuff.i2c_port = GPIOPORTINDEX; - if (viafb_lvds_identify_vt1636()) { + if (viafb_lvds_identify_vt1636(VIA_I2C_ADAP_2C)) { viaparinfo->chip_info->lvds_chip_info.i2c_port = - GPIOPORTINDEX; + VIA_I2C_ADAP_2C; DEBUG_MSG(KERN_INFO - "Found VIA VT1636 LVDS on port gpio 0x2c \n"); + "Found VIA VT1636 LVDS on port gpio 0x2c\n"); } } @@ -421,9 +419,8 @@ static int lvds_register_read(int index) { u8 data; - viaparinfo->shared->i2c_stuff.i2c_port = GPIOPORTINDEX; - viafb_i2c_readbyte((u8) viaparinfo->chip_info-> - lvds_chip_info.lvds_chip_slave_addr, + viafb_i2c_readbyte(VIA_I2C_ADAP_2C, + (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr, (u8) index, &data); return data; } diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index 15543e968248..8f8e0bf0cf91 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -1,5 +1,5 @@ /* - * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. + * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. * This program is free software; you can redistribute it and/or @@ -24,40 +24,44 @@ static void via_i2c_setscl(void *data, int state) { u8 val; - struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data; + struct via_i2c_adap_cfg *adap_data = data; - val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0; + printk(KERN_DEBUG "reading index 0x%02x from IO 0x%x\n", + adap_data->ioport_index, adap_data->io_port); + val = viafb_read_reg(adap_data->io_port, + adap_data->ioport_index) & 0xF0; if (state) val |= 0x20; else val &= ~0x20; - switch (via_i2c_chan->i2c_port) { - case I2CPORTINDEX: + switch (adap_data->type) { + case VIA_I2C_I2C: val |= 0x01; break; - case GPIOPORTINDEX: + case VIA_I2C_GPIO: val |= 0x80; break; default: - DEBUG_MSG("via_i2c: specify wrong i2c port.\n"); + DEBUG_MSG("viafb_i2c: specify wrong i2c type.\n"); } - viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val); + viafb_write_reg(adap_data->ioport_index, + adap_data->io_port, val); } static int via_i2c_getscl(void *data) { - struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data; + struct via_i2c_adap_cfg *adap_data = data; - if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x08) + if (viafb_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08) return 1; return 0; } static int via_i2c_getsda(void *data) { - struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data; + struct via_i2c_adap_cfg *adap_data = data; - if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x04) + if (viafb_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04) return 1; return 0; } @@ -65,27 +69,29 @@ static int via_i2c_getsda(void *data) static void via_i2c_setsda(void *data, int state) { u8 val; - struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data; + struct via_i2c_adap_cfg *adap_data = data; - val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0; + val = viafb_read_reg(adap_data->io_port, + adap_data->ioport_index) & 0xF0; if (state) val |= 0x10; else val &= ~0x10; - switch (via_i2c_chan->i2c_port) { - case I2CPORTINDEX: + switch (adap_data->type) { + case VIA_I2C_I2C: val |= 0x01; break; - case GPIOPORTINDEX: + case VIA_I2C_GPIO: val |= 0x40; break; default: - DEBUG_MSG("via_i2c: specify wrong i2c port.\n"); + DEBUG_MSG("viafb_i2c: specify wrong i2c type.\n"); } - viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val); + viafb_write_reg(adap_data->ioport_index, + adap_data->io_port, val); } -int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata) +int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata) { u8 mm1[] = {0x00}; struct i2c_msg msgs[2]; @@ -97,12 +103,11 @@ int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata) mm1[0] = index; msgs[0].len = 1; msgs[1].len = 1; msgs[0].buf = mm1; msgs[1].buf = pdata; - i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, msgs, 2); - - return 0; + return i2c_transfer(&viaparinfo->shared->i2c_stuff[adap].adapter, + msgs, 2); } -int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data) +int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data) { u8 msg[2] = { index, data }; struct i2c_msg msgs; @@ -111,10 +116,11 @@ int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data) msgs.addr = slave_addr / 2; msgs.len = 2; msgs.buf = msg; - return i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, &msgs, 1); + return i2c_transfer(&viaparinfo->shared->i2c_stuff[adap].adapter, + &msgs, 1); } -int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len) +int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len) { u8 mm1[] = {0x00}; struct i2c_msg msgs[2]; @@ -125,53 +131,88 @@ int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len) mm1[0] = index; msgs[0].len = 1; msgs[1].len = buff_len; msgs[0].buf = mm1; msgs[1].buf = buff; - i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, msgs, 2); - return 0; + return i2c_transfer(&viaparinfo->shared->i2c_stuff[adap].adapter, + msgs, 2); } -int viafb_create_i2c_bus(void *viapar) +static int create_i2c_bus(struct i2c_adapter *adapter, + struct i2c_algo_bit_data *algo, + struct via_i2c_adap_cfg *adap_cfg, + struct pci_dev *pdev) { - int ret; - struct via_i2c_stuff *i2c_stuff = - &((struct viafb_par *)viapar)->shared->i2c_stuff; - - strcpy(i2c_stuff->adapter.name, "via_i2c"); - i2c_stuff->i2c_port = 0x0; - i2c_stuff->adapter.owner = THIS_MODULE; - i2c_stuff->adapter.id = 0x01FFFF; - i2c_stuff->adapter.class = 0; - i2c_stuff->adapter.algo_data = &i2c_stuff->algo; - i2c_stuff->adapter.dev.parent = NULL; - i2c_stuff->algo.setsda = via_i2c_setsda; - i2c_stuff->algo.setscl = via_i2c_setscl; - i2c_stuff->algo.getsda = via_i2c_getsda; - i2c_stuff->algo.getscl = via_i2c_getscl; - i2c_stuff->algo.udelay = 40; - i2c_stuff->algo.timeout = 20; - i2c_stuff->algo.data = i2c_stuff; - - i2c_set_adapdata(&i2c_stuff->adapter, i2c_stuff); + printk(KERN_DEBUG "viafb: creating bus adap=0x%p, algo_bit_data=0x%p, adap_cfg=0x%p\n", adapter, algo, adap_cfg); + + algo->setsda = via_i2c_setsda; + algo->setscl = via_i2c_setscl; + algo->getsda = via_i2c_getsda; + algo->getscl = via_i2c_getscl; + algo->udelay = 40; + algo->timeout = 20; + algo->data = adap_cfg; + + sprintf(adapter->name, "viafb i2c io_port idx 0x%02x", + adap_cfg->ioport_index); + adapter->owner = THIS_MODULE; + adapter->id = 0x01FFFF; + adapter->class = I2C_CLASS_DDC; + adapter->algo_data = algo; + if (pdev) + adapter->dev.parent = &pdev->dev; + else + adapter->dev.parent = NULL; + /* i2c_set_adapdata(adapter, adap_cfg); */ /* Raise SCL and SDA */ - i2c_stuff->i2c_port = I2CPORTINDEX; - via_i2c_setsda(i2c_stuff, 1); - via_i2c_setscl(i2c_stuff, 1); - - i2c_stuff->i2c_port = GPIOPORTINDEX; - via_i2c_setsda(i2c_stuff, 1); - via_i2c_setscl(i2c_stuff, 1); + via_i2c_setsda(adap_cfg, 1); + via_i2c_setscl(adap_cfg, 1); udelay(20); - ret = i2c_bit_add_bus(&i2c_stuff->adapter); - if (ret == 0) - DEBUG_MSG("I2C bus %s registered.\n", i2c_stuff->adapter.name); - else - DEBUG_MSG("Failed to register I2C bus %s.\n", - i2c_stuff->adapter.name); - return ret; + return i2c_bit_add_bus(adapter); +} + +static struct via_i2c_adap_cfg adap_configs[] = { + [VIA_I2C_ADAP_26] = { VIA_I2C_I2C, VIASR, 0x26 }, + [VIA_I2C_ADAP_31] = { VIA_I2C_I2C, VIASR, 0x31 }, + [VIA_I2C_ADAP_25] = { VIA_I2C_GPIO, VIASR, 0x25 }, + [VIA_I2C_ADAP_2C] = { VIA_I2C_GPIO, VIASR, 0x2c }, + [VIA_I2C_ADAP_3D] = { VIA_I2C_GPIO, VIASR, 0x3d }, + { 0, 0, 0 } +}; + +int viafb_create_i2c_busses(struct viafb_par *viapar) +{ + int i, ret; + + for (i = 0; i < VIAFB_NUM_I2C; i++) { + struct via_i2c_adap_cfg *adap_cfg = &adap_configs[i]; + struct via_i2c_stuff *i2c_stuff = &viapar->shared->i2c_stuff[i]; + + if (adap_cfg->type == 0) + break; + + ret = create_i2c_bus(&i2c_stuff->adapter, + &i2c_stuff->algo, adap_cfg, + NULL); /* FIXME: PCIDEV */ + if (ret < 0) { + printk(KERN_ERR "viafb: cannot create i2c bus %u:%d\n", + i, ret); + /* FIXME: properly release previous busses */ + return ret; + } + } + + return 0; } -void viafb_delete_i2c_buss(void *par) +void viafb_delete_i2c_busses(struct viafb_par *par) { - i2c_del_adapter(&((struct viafb_par *)par)->shared->i2c_stuff.adapter); + int i; + + for (i = 0; i < ARRAY_SIZE(par->shared->i2c_stuff); i++) { + struct via_i2c_stuff *i2c_stuff = &par->shared->i2c_stuff[i]; + /* only remove those entries in the array that we've + * actually used (and thus initialized algo_data) */ + if (i2c_stuff->adapter.algo_data == &i2c_stuff->algo) + i2c_del_adapter(&i2c_stuff->adapter); + } } diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_i2c.h index 3a13242a3152..00ed97886842 100644 --- a/drivers/video/via/via_i2c.h +++ b/drivers/video/via/via_i2c.h @@ -1,5 +1,5 @@ /* - * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. + * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. * This program is free software; you can redistribute it and/or @@ -24,23 +24,38 @@ #include #include +enum via_i2c_type { + VIA_I2C_NONE, + VIA_I2C_I2C, + VIA_I2C_GPIO, +}; + +/* private data for each adapter */ +struct via_i2c_adap_cfg { + enum via_i2c_type type; + u_int16_t io_port; + u_int8_t ioport_index; +}; + struct via_i2c_stuff { u16 i2c_port; /* GPIO or I2C port */ struct i2c_adapter adapter; struct i2c_algo_bit_data algo; }; -#define I2CPORT 0x3c4 -#define I2CPORTINDEX 0x31 -#define GPIOPORT 0x3C4 -#define GPIOPORTINDEX 0x2C -#define I2C_BUS 1 -#define GPIO_BUS 2 -#define DELAYPORT 0x3C3 - -int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata); -int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data); -int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len); -int viafb_create_i2c_bus(void *par); -void viafb_delete_i2c_buss(void *par); +enum viafb_i2c_adap { + VIA_I2C_ADAP_26, + VIA_I2C_ADAP_31, + VIA_I2C_ADAP_25, + VIA_I2C_ADAP_2C, + VIA_I2C_ADAP_3D, +}; + +int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata); +int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data); +int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len); + +struct viafb_par; +int viafb_create_i2c_busses(struct viafb_par *par); +void viafb_delete_i2c_busses(struct viafb_par *par); #endif /* __VIA_I2C_H__ */ diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 8955ab4caac8..fa1004997c63 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -1775,7 +1775,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, viafb_dual_fb = 0; /* Set up I2C bus stuff */ - rc = viafb_create_i2c_bus(viaparinfo); + rc = viafb_create_i2c_busses(viaparinfo); if (rc) goto out_fb_release; @@ -1964,7 +1964,7 @@ out_fb1_release: out_unmap_screen: iounmap(viafbinfo->screen_base); out_delete_i2c: - viafb_delete_i2c_buss(viaparinfo); + viafb_delete_i2c_busses(viaparinfo); out_fb_release: framebuffer_release(viafbinfo); return rc; @@ -1980,7 +1980,7 @@ static void __devexit via_pci_remove(struct pci_dev *pdev) iounmap((void *)viafbinfo->screen_base); iounmap(viaparinfo->shared->engine_mmio); - viafb_delete_i2c_buss(viaparinfo); + viafb_delete_i2c_busses(viaparinfo); framebuffer_release(viafbinfo); if (viafb_dual_fb) diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h index 61b5953cd159..4bc00ec8fb1c 100644 --- a/drivers/video/via/viafbdev.h +++ b/drivers/video/via/viafbdev.h @@ -37,11 +37,13 @@ #define VERSION_OS 0 /* 0: for 32 bits OS, 1: for 64 bits OS */ #define VERSION_MINOR 4 +#define VIAFB_NUM_I2C 5 + struct viafb_shared { struct proc_dir_entry *proc_entry; /*viafb proc entry */ /* I2C stuff */ - struct via_i2c_stuff i2c_stuff; + struct via_i2c_stuff i2c_stuff[VIAFB_NUM_I2C]; /* All the information will be needed to set engine */ struct tmds_setting_information tmds_setting_info; diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c index a6b37494e79a..4589c6e73c5d 100644 --- a/drivers/video/via/vt1636.c +++ b/drivers/video/via/vt1636.c @@ -27,9 +27,8 @@ u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information { u8 data; - viaparinfo->shared->i2c_stuff.i2c_port = plvds_chip_info->i2c_port; - viafb_i2c_readbyte(plvds_chip_info->lvds_chip_slave_addr, index, &data); - + viafb_i2c_readbyte(plvds_chip_info->i2c_port, + plvds_chip_info->lvds_chip_slave_addr, index, &data); return data; } @@ -39,14 +38,13 @@ void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information { int index, data; - viaparinfo->shared->i2c_stuff.i2c_port = plvds_chip_info->i2c_port; - index = io_data.Index; data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info, index); data = (data & (~io_data.Mask)) | io_data.Data; - viafb_i2c_writebyte(plvds_chip_info->lvds_chip_slave_addr, index, data); + viafb_i2c_writebyte(plvds_chip_info->i2c_port, + plvds_chip_info->lvds_chip_slave_addr, index, data); } void viafb_init_lvds_vt1636(struct lvds_setting_information @@ -159,7 +157,7 @@ void viafb_disable_lvds_vt1636(struct lvds_setting_information } } -bool viafb_lvds_identify_vt1636(void) +bool viafb_lvds_identify_vt1636(u8 i2c_adapter) { u8 Buffer[2]; @@ -170,23 +168,23 @@ bool viafb_lvds_identify_vt1636(void) VT1636_LVDS_I2C_ADDR; /* Check vendor ID first: */ - viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info. - lvds_chip_slave_addr, - 0x00, &Buffer[0]); - viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info. - lvds_chip_slave_addr, - 0x01, &Buffer[1]); + viafb_i2c_readbyte(i2c_adapter, + (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr, + 0x00, &Buffer[0]); + viafb_i2c_readbyte(i2c_adapter, + (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr, + 0x01, &Buffer[1]); if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11))) return false; /* Check Chip ID: */ - viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info. - lvds_chip_slave_addr, - 0x02, &Buffer[0]); - viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info. - lvds_chip_slave_addr, - 0x03, &Buffer[1]); + viafb_i2c_readbyte(i2c_adapter, + (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr, + 0x02, &Buffer[0]); + viafb_i2c_readbyte(i2c_adapter, + (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr, + 0x03, &Buffer[1]); if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) { viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1636_LVDS; diff --git a/drivers/video/via/vt1636.h b/drivers/video/via/vt1636.h index 2a150c58c7ed..4c1314e57468 100644 --- a/drivers/video/via/vt1636.h +++ b/drivers/video/via/vt1636.h @@ -22,7 +22,7 @@ #ifndef _VT1636_H_ #define _VT1636_H_ #include "chip.h" -bool viafb_lvds_identify_vt1636(void); +bool viafb_lvds_identify_vt1636(u8 i2c_adapter); void viafb_init_lvds_vt1636(struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information *plvds_chip_info); void viafb_enable_lvds_vt1636(struct lvds_setting_information -- cgit v1.2.3 From c774c13dd2826eb91ab6396fd8501df2fc2d83b3 Mon Sep 17 00:00:00 2001 From: Paul Fox Date: Wed, 7 Oct 2009 11:13:01 -0400 Subject: suppress verbose debug messages: change printk() to DEBUG_MSG() [jc: no signoff, added my own] Cc: Florian Tobias Schandinat Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Signed-off-by: Jonathan Corbet --- drivers/video/via/via_i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index 8f8e0bf0cf91..fe5535cf1480 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -26,7 +26,7 @@ static void via_i2c_setscl(void *data, int state) u8 val; struct via_i2c_adap_cfg *adap_data = data; - printk(KERN_DEBUG "reading index 0x%02x from IO 0x%x\n", + DEBUG_MSG(KERN_DEBUG "reading index 0x%02x from IO 0x%x\n", adap_data->ioport_index, adap_data->io_port); val = viafb_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0; @@ -140,7 +140,7 @@ static int create_i2c_bus(struct i2c_adapter *adapter, struct via_i2c_adap_cfg *adap_cfg, struct pci_dev *pdev) { - printk(KERN_DEBUG "viafb: creating bus adap=0x%p, algo_bit_data=0x%p, adap_cfg=0x%p\n", adapter, algo, adap_cfg); + DEBUG_MSG(KERN_DEBUG "viafb: creating bus adap=0x%p, algo_bit_data=0x%p, adap_cfg=0x%p\n", adapter, algo, adap_cfg); algo->setsda = via_i2c_setsda; algo->setscl = via_i2c_setscl; -- cgit v1.2.3 From 4da62e6c6e056d709e5dc04ac7c5e81692cf924f Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Sun, 25 Apr 2010 08:30:41 -0600 Subject: viafb: Only establish i2c busses on ports that always had them ...otherwise it seems we run into conflicts with shadowy other users which don't expect to see i2c taking control of ports it never used to do anything with. Reported-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/via_i2c.c | 19 +++++++++++++------ drivers/video/via/via_i2c.h | 1 + 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index fe5535cf1480..b5253e3099f8 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -170,13 +170,18 @@ static int create_i2c_bus(struct i2c_adapter *adapter, return i2c_bit_add_bus(adapter); } +/* + * By default, we only activate busses on ports 2c and 31 to avoid + * conflicts with other possible users; that default can be changed + * below. + */ static struct via_i2c_adap_cfg adap_configs[] = { - [VIA_I2C_ADAP_26] = { VIA_I2C_I2C, VIASR, 0x26 }, - [VIA_I2C_ADAP_31] = { VIA_I2C_I2C, VIASR, 0x31 }, - [VIA_I2C_ADAP_25] = { VIA_I2C_GPIO, VIASR, 0x25 }, - [VIA_I2C_ADAP_2C] = { VIA_I2C_GPIO, VIASR, 0x2c }, - [VIA_I2C_ADAP_3D] = { VIA_I2C_GPIO, VIASR, 0x3d }, - { 0, 0, 0 } + [VIA_I2C_ADAP_26] = { VIA_I2C_I2C, VIASR, 0x26, 0 }, + [VIA_I2C_ADAP_31] = { VIA_I2C_I2C, VIASR, 0x31, 1 }, + [VIA_I2C_ADAP_25] = { VIA_I2C_GPIO, VIASR, 0x25, 0 }, + [VIA_I2C_ADAP_2C] = { VIA_I2C_GPIO, VIASR, 0x2c, 1 }, + [VIA_I2C_ADAP_3D] = { VIA_I2C_GPIO, VIASR, 0x3d, 0 }, + { 0, 0, 0, 0 } }; int viafb_create_i2c_busses(struct viafb_par *viapar) @@ -189,6 +194,8 @@ int viafb_create_i2c_busses(struct viafb_par *viapar) if (adap_cfg->type == 0) break; + if (!adap_cfg->is_active) + continue; ret = create_i2c_bus(&i2c_stuff->adapter, &i2c_stuff->algo, adap_cfg, diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_i2c.h index 00ed97886842..73d682fcf269 100644 --- a/drivers/video/via/via_i2c.h +++ b/drivers/video/via/via_i2c.h @@ -35,6 +35,7 @@ struct via_i2c_adap_cfg { enum via_i2c_type type; u_int16_t io_port; u_int8_t ioport_index; + u8 is_active; }; struct via_i2c_stuff { -- cgit v1.2.3 From 7d7fb0e6eb78600e5d4fb0f28858e97d38ef6bbf Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Wed, 28 Apr 2010 12:25:02 +0200 Subject: cocbalt_lcdfb: correct sections Since the drivers probe call was changed from .init.text to .devinit.text in commit c2e13037e6794bd0d9de3f9ecabf5615f15c160b the fb_fix_screeninfo structure must be changed from .init.data to .devinit.data, too. Signed-off-by: Henrik Kretzschmar Tested-by: Ralf Baechle Signed-off-by: Jiri Kosina --- drivers/video/cobalt_lcdfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index 5eb61b5adfe8..42fe155aba0e 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c @@ -123,7 +123,7 @@ static void lcd_clear(struct fb_info *info) lcd_write_control(info, LCD_RESET); } -static struct fb_fix_screeninfo cobalt_lcdfb_fix __initdata = { +static struct fb_fix_screeninfo cobalt_lcdfb_fix __devinitdata = { .id = "cobalt-lcd", .type = FB_TYPE_TEXT, .type_aux = FB_AUX_TEXT_MDA, -- cgit v1.2.3 From 8bed90557d2600d25e58de30df48b244980164ec Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 30 Apr 2010 16:07:00 +0000 Subject: sh: fix a number of Oopses and leaks in SH framebuffer driver Fix a number of Oopses, memory leaks and unbalanced calls on error paths in sh_mobile_lcdcfb.c. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- drivers/video/sh_mobile_lcdcfb.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index e14bd0749129..e8c769944812 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -695,6 +695,7 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, * 1) Enable Runtime PM * 2) Force Runtime PM Resume since hardware is accessed from probe() */ + priv->dev = &pdev->dev; pm_runtime_enable(priv->dev); pm_runtime_resume(priv->dev); return 0; @@ -957,25 +958,24 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) if (!pdev->dev.platform_data) { dev_err(&pdev->dev, "no platform data defined\n"); - error = -EINVAL; - goto err0; + return -EINVAL; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); i = platform_get_irq(pdev, 0); if (!res || i < 0) { dev_err(&pdev->dev, "cannot get platform resources\n"); - error = -ENOENT; - goto err0; + return -ENOENT; } priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { dev_err(&pdev->dev, "cannot allocate device data\n"); - error = -ENOMEM; - goto err0; + return -ENOMEM; } + platform_set_drvdata(pdev, priv); + error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED, dev_name(&pdev->dev), priv); if (error) { @@ -984,8 +984,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) } priv->irq = i; - priv->dev = &pdev->dev; - platform_set_drvdata(pdev, priv); pdata = pdev->dev.platform_data; j = 0; @@ -1099,9 +1097,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) info = ch->info; if (info->fbdefio) { - priv->ch->sglist = vmalloc(sizeof(struct scatterlist) * + ch->sglist = vmalloc(sizeof(struct scatterlist) * info->fix.smem_len >> PAGE_SHIFT); - if (!priv->ch->sglist) { + if (!ch->sglist) { dev_err(&pdev->dev, "cannot allocate sglist\n"); goto err1; } @@ -1126,9 +1124,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) } return 0; - err1: +err1: sh_mobile_lcdc_remove(pdev); - err0: + return error; } @@ -1139,7 +1137,7 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) int i; for (i = 0; i < ARRAY_SIZE(priv->ch); i++) - if (priv->ch[i].info->dev) + if (priv->ch[i].info && priv->ch[i].info->dev) unregister_framebuffer(priv->ch[i].info); sh_mobile_lcdc_stop(priv); @@ -1162,7 +1160,8 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) if (priv->dot_clk) clk_put(priv->dot_clk); - pm_runtime_disable(priv->dev); + if (priv->dev) + pm_runtime_disable(priv->dev); if (priv->base) iounmap(priv->base); -- cgit v1.2.3 From f045f77bc0bf238a871b10bea9e425329a8e4abc Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Tue, 1 Dec 2009 20:29:39 -0700 Subject: viafb: Move core stuff into via-core.c The first step toward turning viafb into a multifunction driver. This patch creates a new via-core.c file which serves as the main PCI driver; everything else comes below that. Some work has been done to rationalize the i2c drivers in this new scheme. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/Makefile | 2 +- drivers/video/via/dvi.c | 4 +- drivers/video/via/global.h | 1 + drivers/video/via/lcd.c | 10 ++-- drivers/video/via/via-core.c | 116 +++++++++++++++++++++++++++++++++++++++++++ drivers/video/via/via-core.h | 55 ++++++++++++++++++++ drivers/video/via/via_i2c.c | 74 ++++++++++++--------------- drivers/video/via/via_i2c.h | 26 ++-------- drivers/video/via/viafbdev.c | 69 ++++++------------------- drivers/video/via/viafbdev.h | 17 +++++-- 10 files changed, 242 insertions(+), 132 deletions(-) create mode 100644 drivers/video/via/via-core.c create mode 100644 drivers/video/via/via-core.h (limited to 'drivers/video') diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile index eeed238ad6a2..aec3f8b24a96 100644 --- a/drivers/video/via/Makefile +++ b/drivers/video/via/Makefile @@ -4,4 +4,4 @@ obj-$(CONFIG_FB_VIA) += viafb.o -viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o +viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o via-core.o diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c index be513701e4e6..e357c4d1cd0f 100644 --- a/drivers/video/via/dvi.c +++ b/drivers/video/via/dvi.c @@ -96,7 +96,7 @@ int viafb_tmds_trasmitter_identify(void) viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS; viaparinfo->chip_info-> tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; - viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_I2C_ADAP_31; + viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31; if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) { /* * Currently only support 12bits,dual edge,add 24bits mode later @@ -110,7 +110,7 @@ int viafb_tmds_trasmitter_identify(void) viaparinfo->chip_info->tmds_chip_info.i2c_port); return OK; } else { - viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_I2C_ADAP_2C; + viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_2C; if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) { tmds_register_write(0x08, 0x3b); diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h index 8d95d5fd1388..be48e73da045 100644 --- a/drivers/video/via/global.h +++ b/drivers/video/via/global.h @@ -35,6 +35,7 @@ #include "debug.h" +#include "via-core.h" #include "viafbdev.h" #include "chip.h" #include "accel.h" diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index e19441d9e49f..8ef60c035fa2 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c @@ -172,14 +172,14 @@ static bool lvds_identify_integratedlvds(void) int viafb_lvds_trasmitter_identify(void) { - if (viafb_lvds_identify_vt1636(VIA_I2C_ADAP_31)) { - viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_I2C_ADAP_31; + if (viafb_lvds_identify_vt1636(VIA_PORT_31)) { + viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31; DEBUG_MSG(KERN_INFO "Found VIA VT1636 LVDS on port i2c 0x31\n"); } else { - if (viafb_lvds_identify_vt1636(VIA_I2C_ADAP_2C)) { + if (viafb_lvds_identify_vt1636(VIA_PORT_2C)) { viaparinfo->chip_info->lvds_chip_info.i2c_port = - VIA_I2C_ADAP_2C; + VIA_PORT_2C; DEBUG_MSG(KERN_INFO "Found VIA VT1636 LVDS on port gpio 0x2c\n"); } @@ -419,7 +419,7 @@ static int lvds_register_read(int index) { u8 data; - viafb_i2c_readbyte(VIA_I2C_ADAP_2C, + viafb_i2c_readbyte(VIA_PORT_2C, (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr, (u8) index, &data); return data; diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c new file mode 100644 index 000000000000..e7201470cf35 --- /dev/null +++ b/drivers/video/via/via-core.c @@ -0,0 +1,116 @@ +/* + * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. + * Copyright 2009 Jonathan Corbet + */ + +/* + * Core code for the Via multifunction framebuffer device. + */ +#include +#include +#include "global.h" /* Includes everything under the sun */ + +/* + * The default port config. + */ +static struct via_port_cfg adap_configs[] = { + [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_OFF, VIASR, 0x26 }, + [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 }, + [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 }, + [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c }, + [VIA_PORT_3D] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d }, + { 0, 0, 0, 0 } +}; + + +static int __devinit via_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int ret; + + ret = pci_enable_device(pdev); + if (ret) + return ret; + /* + * Create the I2C busses. Bailing out on failure seems extreme, + * but that's what the code did before. + */ + ret = viafb_create_i2c_busses(adap_configs); + if (ret) + goto out_disable; + /* + * Set up the framebuffer. + */ + ret = via_fb_pci_probe(pdev, ent); + if (ret) + goto out_i2c; + return 0; + +out_i2c: + viafb_delete_i2c_busses(); +out_disable: + pci_disable_device(pdev); + return ret; +} + +static void __devexit via_pci_remove(struct pci_dev *pdev) +{ + viafb_delete_i2c_busses(); + via_fb_pci_remove(pdev); + pci_disable_device(pdev); +} + + +static struct pci_device_id via_pci_table[] __devinitdata = { + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID), + .driver_data = UNICHROME_CLE266 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID), + .driver_data = UNICHROME_PM800 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID), + .driver_data = UNICHROME_K400 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID), + .driver_data = UNICHROME_K800 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID), + .driver_data = UNICHROME_CN700 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID), + .driver_data = UNICHROME_K8M890 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID), + .driver_data = UNICHROME_CX700 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID), + .driver_data = UNICHROME_P4M900 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID), + .driver_data = UNICHROME_CN750 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID), + .driver_data = UNICHROME_VX800 }, + { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID), + .driver_data = UNICHROME_VX855 }, + { } +}; +MODULE_DEVICE_TABLE(pci, via_pci_table); + +static struct pci_driver via_driver = { + .name = "viafb", + .id_table = via_pci_table, + .probe = via_pci_probe, + .remove = __devexit_p(via_pci_remove), +}; + +static int __init via_core_init(void) +{ + int ret; + + ret = viafb_init(); + if (ret) + return ret; + return pci_register_driver(&via_driver); +} + +static void __exit via_core_exit(void) +{ + pci_unregister_driver(&via_driver); + viafb_exit(); +} + +module_init(via_core_init); +module_exit(via_core_exit); diff --git a/drivers/video/via/via-core.h b/drivers/video/via/via-core.h new file mode 100644 index 000000000000..1c2fb06b77ae --- /dev/null +++ b/drivers/video/via/via-core.h @@ -0,0 +1,55 @@ +/* + * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. + * Copyright 2009 Jonathan Corbet + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; + * either version 2, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE.See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __VIA_CORE_H__ +#define __VIA_CORE_H__ +/* + * A description of each known serial I2C/GPIO port. + */ +enum via_port_type { + VIA_PORT_NONE = 0, + VIA_PORT_I2C, + VIA_PORT_GPIO, +}; + +enum via_port_mode { + VIA_MODE_OFF = 0, + VIA_MODE_I2C, /* Used as I2C port */ + VIA_MODE_GPIO, /* Two GPIO ports */ +}; + +enum viafb_i2c_adap { + VIA_PORT_26 = 0, + VIA_PORT_31, + VIA_PORT_25, + VIA_PORT_2C, + VIA_PORT_3D, +}; +#define VIAFB_NUM_PORTS 5 + +struct via_port_cfg { + enum via_port_type type; + enum via_port_mode mode; + u_int16_t io_port; + u_int8_t ioport_index; +}; +#endif /* __VIA_CORE_H__ */ diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index b5253e3099f8..478829281562 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -21,13 +21,18 @@ #include "global.h" +/* + * There can only be one set of these, so there's no point in having + * them be dynamically allocated... + */ +#define VIAFB_NUM_I2C 5 +static struct via_i2c_stuff via_i2c_par[VIAFB_NUM_I2C]; + static void via_i2c_setscl(void *data, int state) { u8 val; - struct via_i2c_adap_cfg *adap_data = data; + struct via_port_cfg *adap_data = data; - DEBUG_MSG(KERN_DEBUG "reading index 0x%02x from IO 0x%x\n", - adap_data->ioport_index, adap_data->io_port); val = viafb_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0; if (state) @@ -35,10 +40,10 @@ static void via_i2c_setscl(void *data, int state) else val &= ~0x20; switch (adap_data->type) { - case VIA_I2C_I2C: + case VIA_PORT_I2C: val |= 0x01; break; - case VIA_I2C_GPIO: + case VIA_PORT_GPIO: val |= 0x80; break; default: @@ -50,7 +55,7 @@ static void via_i2c_setscl(void *data, int state) static int via_i2c_getscl(void *data) { - struct via_i2c_adap_cfg *adap_data = data; + struct via_port_cfg *adap_data = data; if (viafb_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08) return 1; @@ -59,7 +64,7 @@ static int via_i2c_getscl(void *data) static int via_i2c_getsda(void *data) { - struct via_i2c_adap_cfg *adap_data = data; + struct via_port_cfg *adap_data = data; if (viafb_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04) return 1; @@ -69,7 +74,7 @@ static int via_i2c_getsda(void *data) static void via_i2c_setsda(void *data, int state) { u8 val; - struct via_i2c_adap_cfg *adap_data = data; + struct via_port_cfg *adap_data = data; val = viafb_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0; @@ -78,10 +83,10 @@ static void via_i2c_setsda(void *data, int state) else val &= ~0x10; switch (adap_data->type) { - case VIA_I2C_I2C: + case VIA_PORT_I2C: val |= 0x01; break; - case VIA_I2C_GPIO: + case VIA_PORT_GPIO: val |= 0x40; break; default: @@ -103,8 +108,7 @@ int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata) mm1[0] = index; msgs[0].len = 1; msgs[1].len = 1; msgs[0].buf = mm1; msgs[1].buf = pdata; - return i2c_transfer(&viaparinfo->shared->i2c_stuff[adap].adapter, - msgs, 2); + return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2); } int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data) @@ -116,8 +120,7 @@ int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data) msgs.addr = slave_addr / 2; msgs.len = 2; msgs.buf = msg; - return i2c_transfer(&viaparinfo->shared->i2c_stuff[adap].adapter, - &msgs, 1); + return i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1); } int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len) @@ -131,13 +134,12 @@ int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len mm1[0] = index; msgs[0].len = 1; msgs[1].len = buff_len; msgs[0].buf = mm1; msgs[1].buf = buff; - return i2c_transfer(&viaparinfo->shared->i2c_stuff[adap].adapter, - msgs, 2); + return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2); } static int create_i2c_bus(struct i2c_adapter *adapter, struct i2c_algo_bit_data *algo, - struct via_i2c_adap_cfg *adap_cfg, + struct via_port_cfg *adap_cfg, struct pci_dev *pdev) { DEBUG_MSG(KERN_DEBUG "viafb: creating bus adap=0x%p, algo_bit_data=0x%p, adap_cfg=0x%p\n", adapter, algo, adap_cfg); @@ -170,31 +172,15 @@ static int create_i2c_bus(struct i2c_adapter *adapter, return i2c_bit_add_bus(adapter); } -/* - * By default, we only activate busses on ports 2c and 31 to avoid - * conflicts with other possible users; that default can be changed - * below. - */ -static struct via_i2c_adap_cfg adap_configs[] = { - [VIA_I2C_ADAP_26] = { VIA_I2C_I2C, VIASR, 0x26, 0 }, - [VIA_I2C_ADAP_31] = { VIA_I2C_I2C, VIASR, 0x31, 1 }, - [VIA_I2C_ADAP_25] = { VIA_I2C_GPIO, VIASR, 0x25, 0 }, - [VIA_I2C_ADAP_2C] = { VIA_I2C_GPIO, VIASR, 0x2c, 1 }, - [VIA_I2C_ADAP_3D] = { VIA_I2C_GPIO, VIASR, 0x3d, 0 }, - { 0, 0, 0, 0 } -}; - -int viafb_create_i2c_busses(struct viafb_par *viapar) +int viafb_create_i2c_busses(struct via_port_cfg *configs) { int i, ret; - for (i = 0; i < VIAFB_NUM_I2C; i++) { - struct via_i2c_adap_cfg *adap_cfg = &adap_configs[i]; - struct via_i2c_stuff *i2c_stuff = &viapar->shared->i2c_stuff[i]; + for (i = 0; i < VIAFB_NUM_PORTS; i++) { + struct via_port_cfg *adap_cfg = configs++; + struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i]; - if (adap_cfg->type == 0) - break; - if (!adap_cfg->is_active) + if (adap_cfg->type == 0 || adap_cfg->mode != VIA_MODE_I2C) continue; ret = create_i2c_bus(&i2c_stuff->adapter, @@ -211,14 +197,16 @@ int viafb_create_i2c_busses(struct viafb_par *viapar) return 0; } -void viafb_delete_i2c_busses(struct viafb_par *par) +void viafb_delete_i2c_busses(void) { int i; - for (i = 0; i < ARRAY_SIZE(par->shared->i2c_stuff); i++) { - struct via_i2c_stuff *i2c_stuff = &par->shared->i2c_stuff[i]; - /* only remove those entries in the array that we've - * actually used (and thus initialized algo_data) */ + for (i = 0; i < VIAFB_NUM_PORTS; i++) { + struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i]; + /* + * Only remove those entries in the array that we've + * actually used (and thus initialized algo_data) + */ if (i2c_stuff->adapter.algo_data == &i2c_stuff->algo) i2c_del_adapter(&i2c_stuff->adapter); } diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_i2c.h index 73d682fcf269..00932914b4ed 100644 --- a/drivers/video/via/via_i2c.h +++ b/drivers/video/via/via_i2c.h @@ -24,39 +24,19 @@ #include #include -enum via_i2c_type { - VIA_I2C_NONE, - VIA_I2C_I2C, - VIA_I2C_GPIO, -}; - -/* private data for each adapter */ -struct via_i2c_adap_cfg { - enum via_i2c_type type; - u_int16_t io_port; - u_int8_t ioport_index; - u8 is_active; -}; - struct via_i2c_stuff { u16 i2c_port; /* GPIO or I2C port */ struct i2c_adapter adapter; struct i2c_algo_bit_data algo; }; -enum viafb_i2c_adap { - VIA_I2C_ADAP_26, - VIA_I2C_ADAP_31, - VIA_I2C_ADAP_25, - VIA_I2C_ADAP_2C, - VIA_I2C_ADAP_3D, -}; int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata); int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data); int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len); struct viafb_par; -int viafb_create_i2c_busses(struct viafb_par *par); -void viafb_delete_i2c_busses(struct viafb_par *par); +int viafb_create_i2c_busses(struct via_port_cfg *cfg); +void viafb_delete_i2c_busses(void); +struct i2c_adapter *viafb_find_adapter(enum viafb_i2c_adap which); #endif /* __VIA_I2C_H__ */ diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index fa1004997c63..17a874f6ea1c 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -1731,8 +1731,9 @@ static int parse_mode(const char *str, u32 *xres, u32 *yres) return 0; } -static int __devinit via_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) + +int __devinit via_fb_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { u32 default_xres, default_yres; struct VideoModeTable *vmode_entry; @@ -1764,6 +1765,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, &viaparinfo->shared->lvds_setting_info2; viaparinfo->crt_setting_info = &viaparinfo->shared->crt_setting_info; viaparinfo->chip_info = &viaparinfo->shared->chip_info; + spin_lock_init(&viaparinfo->reg_lock); if (viafb_dual_fb) viafb_SAMM_ON = 1; @@ -1774,26 +1776,21 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, if (!viafb_SAMM_ON) viafb_dual_fb = 0; - /* Set up I2C bus stuff */ - rc = viafb_create_i2c_busses(viaparinfo); - if (rc) - goto out_fb_release; - viafb_init_chip_info(pdev, ent); viaparinfo->fbmem = pci_resource_start(pdev, 0); viaparinfo->memsize = viafb_get_fb_size_from_pci(); if (viaparinfo->memsize < 0) { rc = viaparinfo->memsize; - goto out_delete_i2c; + goto out_fb_release; } viaparinfo->fbmem_free = viaparinfo->memsize; viaparinfo->fbmem_used = 0; viafbinfo->screen_base = ioremap_nocache(viaparinfo->fbmem, viaparinfo->memsize); if (!viafbinfo->screen_base) { - printk(KERN_INFO "ioremap failed\n"); + printk(KERN_ERR "ioremap of fbmem failed\n"); rc = -ENOMEM; - goto out_delete_i2c; + goto out_fb_release; } viafbinfo->fix.mmio_start = pci_resource_start(pdev, 1); @@ -1963,14 +1960,12 @@ out_fb1_release: framebuffer_release(viafbinfo1); out_unmap_screen: iounmap(viafbinfo->screen_base); -out_delete_i2c: - viafb_delete_i2c_busses(viaparinfo); out_fb_release: framebuffer_release(viafbinfo); return rc; } -static void __devexit via_pci_remove(struct pci_dev *pdev) +void __devexit via_fb_pci_remove(struct pci_dev *pdev) { DEBUG_MSG(KERN_INFO "via_pci_remove!\n"); fb_dealloc_cmap(&viafbinfo->cmap); @@ -1980,8 +1975,6 @@ static void __devexit via_pci_remove(struct pci_dev *pdev) iounmap((void *)viafbinfo->screen_base); iounmap(viaparinfo->shared->engine_mmio); - viafb_delete_i2c_busses(viaparinfo); - framebuffer_release(viafbinfo); if (viafb_dual_fb) framebuffer_release(viafbinfo1); @@ -2062,41 +2055,10 @@ static int __init viafb_setup(char *options) } #endif -static struct pci_device_id viafb_pci_table[] __devinitdata = { - { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID), - .driver_data = UNICHROME_CLE266 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID), - .driver_data = UNICHROME_PM800 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID), - .driver_data = UNICHROME_K400 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID), - .driver_data = UNICHROME_K800 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID), - .driver_data = UNICHROME_CN700 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID), - .driver_data = UNICHROME_K8M890 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID), - .driver_data = UNICHROME_CX700 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID), - .driver_data = UNICHROME_P4M900 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID), - .driver_data = UNICHROME_CN750 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID), - .driver_data = UNICHROME_VX800 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID), - .driver_data = UNICHROME_VX855 }, - { } -}; -MODULE_DEVICE_TABLE(pci, viafb_pci_table); - -static struct pci_driver viafb_driver = { - .name = "viafb", - .id_table = viafb_pci_table, - .probe = via_pci_probe, - .remove = __devexit_p(via_pci_remove), -}; - -static int __init viafb_init(void) +/* + * These are called out of via-core for now. + */ +int __init viafb_init(void) { u32 dummy; #ifndef MODULE @@ -2115,13 +2077,12 @@ static int __init viafb_init(void) printk(KERN_INFO "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", VERSION_MAJOR, VERSION_MINOR); - return pci_register_driver(&viafb_driver); + return 0; } -static void __exit viafb_exit(void) +void __exit viafb_exit(void) { DEBUG_MSG(KERN_INFO "viafb_exit!\n"); - pci_unregister_driver(&viafb_driver); } static struct fb_ops viafb_ops = { @@ -2141,8 +2102,6 @@ static struct fb_ops viafb_ops = { .fb_sync = viafb_sync, }; -module_init(viafb_init); -module_exit(viafb_exit); #ifdef MODULE module_param(viafb_mode, charp, S_IRUSR); diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h index 4bc00ec8fb1c..5604f27eb74e 100644 --- a/drivers/video/via/viafbdev.h +++ b/drivers/video/via/viafbdev.h @@ -24,6 +24,7 @@ #include #include +#include #include "ioctl.h" #include "share.h" @@ -42,9 +43,6 @@ struct viafb_shared { struct proc_dir_entry *proc_entry; /*viafb proc entry */ - /* I2C stuff */ - struct via_i2c_stuff i2c_stuff[VIAFB_NUM_I2C]; - /* All the information will be needed to set engine */ struct tmds_setting_information tmds_setting_info; struct crt_setting_information crt_setting_info; @@ -74,6 +72,14 @@ struct viafb_par { struct viafb_shared *shared; + /* + * (jc) I believe one should use locking to protect against + * concurrent access to the device ports and registers. Thus, + * this lock. Use of it is *far* from universal, though... + * someday... + */ + spinlock_t reg_lock; + /* All the information will be needed to set engine */ /* depreciated, use the ones in shared directly */ struct tmds_setting_information *tmds_setting_info; @@ -101,4 +107,9 @@ u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information *plvds_chip_info, struct IODATA io_data); +int via_fb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent); +void via_fb_pci_remove(struct pci_dev *pdev); +/* Temporary */ +int viafb_init(void); +void viafb_exit(void); #endif /* __VIAFBDEV_H__ */ -- cgit v1.2.3 From 24b4d82e4715841848a499534ed5cb7db3d6bca3 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Thu, 22 Apr 2010 13:48:09 -0600 Subject: viafb: Separate global and fb-specific data This patch moves data of interest into a new viafb_dev structure which describes the device as a whole; the idea here is to create a separation between what all devices may need and what the framebuffer device in particular needs. I've also made some small steps toward thinning out the global.h mess. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/accel.c | 14 ++-- drivers/video/via/dvi.c | 2 + drivers/video/via/global.h | 2 - drivers/video/via/hw.c | 131 ++---------------------------- drivers/video/via/hw.h | 4 +- drivers/video/via/lcd.c | 3 +- drivers/video/via/via-core.c | 185 ++++++++++++++++++++++++++++++++++++++++++- drivers/video/via/via-core.h | 38 ++++++++- drivers/video/via/via_i2c.c | 2 + drivers/video/via/viafbdev.c | 54 ++++++------- drivers/video/via/viafbdev.h | 13 +-- drivers/video/via/vt1636.c | 2 + 12 files changed, 265 insertions(+), 185 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index 0d90c859cc1c..e77746857c8f 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -18,6 +18,7 @@ * Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "via-core.h" #include "global.h" /* @@ -321,8 +322,7 @@ int viafb_init_engine(struct fb_info *info) u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high, vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name; - engine = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); - viapar->shared->engine_mmio = engine; + engine = viapar->shared->vdev->engine_mmio; if (!engine) { printk(KERN_WARNING "viafb_init_accel: ioremap failed, " "hardware acceleration disabled\n"); @@ -465,7 +465,7 @@ void viafb_show_hw_cursor(struct fb_info *info, int Status) struct viafb_par *viapar = info->par; u32 temp, iga_path = viapar->iga_path; - temp = readl(viapar->shared->engine_mmio + VIA_REG_CURSOR_MODE); + temp = readl(viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE); switch (Status) { case HW_Cursor_ON: temp |= 0x1; @@ -482,7 +482,7 @@ void viafb_show_hw_cursor(struct fb_info *info, int Status) default: temp &= 0x7FFFFFFF; } - writel(temp, viapar->shared->engine_mmio + VIA_REG_CURSOR_MODE); + writel(temp, viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE); } void viafb_wait_engine_idle(struct fb_info *info) @@ -490,6 +490,7 @@ void viafb_wait_engine_idle(struct fb_info *info) struct viafb_par *viapar = info->par; int loop = 0; u32 mask; + void __iomem *engine = viapar->shared->vdev->engine_mmio; switch (viapar->shared->chip_info.twod_engine) { case VIA_2D_ENG_H5: @@ -498,7 +499,7 @@ void viafb_wait_engine_idle(struct fb_info *info) VIA_3D_ENG_BUSY_M1; break; default: - while (!(readl(viapar->shared->engine_mmio + VIA_REG_STATUS) & + while (!(readl(engine + VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { loop++; cpu_relax(); @@ -507,8 +508,7 @@ void viafb_wait_engine_idle(struct fb_info *info) break; } - while ((readl(viapar->shared->engine_mmio + VIA_REG_STATUS) & mask) && - (loop < MAXLOOP)) { + while ((readl(engine + VIA_REG_STATUS) & mask) && (loop < MAXLOOP)) { loop++; cpu_relax(); } diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c index e357c4d1cd0f..6271b7696323 100644 --- a/drivers/video/via/dvi.c +++ b/drivers/video/via/dvi.c @@ -18,6 +18,8 @@ * Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "via-core.h" +#include "via_i2c.h" #include "global.h" static void tmds_register_write(int index, u8 data); diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h index be48e73da045..28221a062dda 100644 --- a/drivers/video/via/global.h +++ b/drivers/video/via/global.h @@ -35,14 +35,12 @@ #include "debug.h" -#include "via-core.h" #include "viafbdev.h" #include "chip.h" #include "accel.h" #include "share.h" #include "dvi.h" #include "viamode.h" -#include "via_i2c.h" #include "hw.h" #include "lcd.h" diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 2322612fbb95..f2425ae228ae 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -18,7 +18,7 @@ * Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - +#include "via-core.h" #include "global.h" static struct pll_map pll_value[] = { @@ -526,8 +526,7 @@ static void dvi_patch_skew_dvp_low(void); static void set_dvi_output_path(int set_iga, int output_interface); static void set_lcd_output_path(int set_iga, int output_interface); static void load_fix_bit_crtc_reg(void); -static void init_gfx_chip_info(struct pci_dev *pdev, - const struct pci_device_id *pdi); +static void init_gfx_chip_info(int chip_type); static void init_tmds_chip_info(void); static void init_lvds_chip_info(void); static void device_screen_off(void); @@ -1911,10 +1910,9 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, } -void viafb_init_chip_info(struct pci_dev *pdev, - const struct pci_device_id *pdi) +void viafb_init_chip_info(int chip_type) { - init_gfx_chip_info(pdev, pdi); + init_gfx_chip_info(chip_type); init_tmds_chip_info(); init_lvds_chip_info(); @@ -1981,12 +1979,11 @@ void viafb_update_device_setting(int hres, int vres, } } -static void init_gfx_chip_info(struct pci_dev *pdev, - const struct pci_device_id *pdi) +static void init_gfx_chip_info(int chip_type) { u8 tmp; - viaparinfo->chip_info->gfx_chip_name = pdi->driver_data; + viaparinfo->chip_info->gfx_chip_name = chip_type; /* Check revision of CLE266 Chip */ if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { @@ -2489,122 +2486,6 @@ static void disable_second_display_channel(void) viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6); } -static u_int16_t via_function3[] = { - CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3, - CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3, - P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, -}; - -/* Get the BIOS-configured framebuffer size from PCI configuration space - * of function 3 in the respective chipset */ -int viafb_get_fb_size_from_pci(void) -{ - int i; - u_int8_t offset = 0; - u_int32_t FBSize; - u_int32_t VideoMemSize; - - /* search for the "FUNCTION3" device in this chipset */ - for (i = 0; i < ARRAY_SIZE(via_function3); i++) { - struct pci_dev *pdev; - - pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i], - NULL); - if (!pdev) - continue; - - DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device); - - switch (pdev->device) { - case CLE266_FUNCTION3: - case KM400_FUNCTION3: - offset = 0xE0; - break; - case CN400_FUNCTION3: - case CN700_FUNCTION3: - case CX700_FUNCTION3: - case KM800_FUNCTION3: - case KM890_FUNCTION3: - case P4M890_FUNCTION3: - case P4M900_FUNCTION3: - case VX800_FUNCTION3: - case VX855_FUNCTION3: - /*case CN750_FUNCTION3: */ - offset = 0xA0; - break; - } - - if (!offset) - break; - - pci_read_config_dword(pdev, offset, &FBSize); - pci_dev_put(pdev); - } - - if (!offset) { - printk(KERN_ERR "cannot determine framebuffer size\n"); - return -EIO; - } - - FBSize = FBSize & 0x00007000; - DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize); - - if (viaparinfo->chip_info->gfx_chip_name < UNICHROME_CX700) { - switch (FBSize) { - case 0x00004000: - VideoMemSize = (16 << 20); /*16M */ - break; - - case 0x00005000: - VideoMemSize = (32 << 20); /*32M */ - break; - - case 0x00006000: - VideoMemSize = (64 << 20); /*64M */ - break; - - default: - VideoMemSize = (32 << 20); /*32M */ - break; - } - } else { - switch (FBSize) { - case 0x00001000: - VideoMemSize = (8 << 20); /*8M */ - break; - - case 0x00002000: - VideoMemSize = (16 << 20); /*16M */ - break; - - case 0x00003000: - VideoMemSize = (32 << 20); /*32M */ - break; - - case 0x00004000: - VideoMemSize = (64 << 20); /*64M */ - break; - - case 0x00005000: - VideoMemSize = (128 << 20); /*128M */ - break; - - case 0x00006000: - VideoMemSize = (256 << 20); /*256M */ - break; - - case 0x00007000: /* Only on VX855/875 */ - VideoMemSize = (512 << 20); /*512M */ - break; - - default: - VideoMemSize = (32 << 20); /*32M */ - break; - } - } - - return VideoMemSize; -} void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ *p_gfx_dpa_setting) diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index d6b25acd4a99..d248f4dc12ec 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -900,15 +900,13 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, struct VideoModeTable *vmode_tbl1, int video_bpp1); void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, struct VideoModeTable *vmode_tbl); -void viafb_init_chip_info(struct pci_dev *pdev, - const struct pci_device_id *pdi); +void viafb_init_chip_info(int chip_type); void viafb_init_dac(int set_iga); int viafb_get_pixclock(int hres, int vres, int vmode_refresh); int viafb_get_refresh(int hres, int vres, u32 float_refresh); void viafb_update_device_setting(int hres, int vres, int bpp, int vmode_refresh, int flag); -int viafb_get_fb_size_from_pci(void); void viafb_set_iga_path(void); void viafb_set_primary_address(u32 addr); void viafb_set_secondary_address(u32 addr); diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index 8ef60c035fa2..04eec31aa9a2 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c @@ -18,7 +18,8 @@ * Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - +#include "via-core.h" +#include "via_i2c.h" #include "global.h" #include "lcdtbl.h" diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index e7201470cf35..b77cd5c2fc96 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c @@ -7,9 +7,12 @@ /* * Core code for the Via multifunction framebuffer device. */ +#include "via-core.h" +#include "via_i2c.h" +#include "global.h" + #include #include -#include "global.h" /* Includes everything under the sun */ /* * The default port config. @@ -23,6 +26,169 @@ static struct via_port_cfg adap_configs[] = { { 0, 0, 0, 0 } }; +/* + * We currently only support one viafb device (will there ever be + * more than one?), so just declare it globally here. + */ +static struct viafb_dev global_dev; + + +/* + * Figure out how big our framebuffer memory is. Kind of ugly, + * but evidently we can't trust the information found in the + * fbdev configuration area. + */ +static u16 via_function3[] = { + CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3, + CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3, + P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, +}; + +/* Get the BIOS-configured framebuffer size from PCI configuration space + * of function 3 in the respective chipset */ +static int viafb_get_fb_size_from_pci(int chip_type) +{ + int i; + u8 offset = 0; + u32 FBSize; + u32 VideoMemSize; + + /* search for the "FUNCTION3" device in this chipset */ + for (i = 0; i < ARRAY_SIZE(via_function3); i++) { + struct pci_dev *pdev; + + pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i], + NULL); + if (!pdev) + continue; + + DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device); + + switch (pdev->device) { + case CLE266_FUNCTION3: + case KM400_FUNCTION3: + offset = 0xE0; + break; + case CN400_FUNCTION3: + case CN700_FUNCTION3: + case CX700_FUNCTION3: + case KM800_FUNCTION3: + case KM890_FUNCTION3: + case P4M890_FUNCTION3: + case P4M900_FUNCTION3: + case VX800_FUNCTION3: + case VX855_FUNCTION3: + /*case CN750_FUNCTION3: */ + offset = 0xA0; + break; + } + + if (!offset) + break; + + pci_read_config_dword(pdev, offset, &FBSize); + pci_dev_put(pdev); + } + + if (!offset) { + printk(KERN_ERR "cannot determine framebuffer size\n"); + return -EIO; + } + + FBSize = FBSize & 0x00007000; + DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize); + + if (chip_type < UNICHROME_CX700) { + switch (FBSize) { + case 0x00004000: + VideoMemSize = (16 << 20); /*16M */ + break; + + case 0x00005000: + VideoMemSize = (32 << 20); /*32M */ + break; + + case 0x00006000: + VideoMemSize = (64 << 20); /*64M */ + break; + + default: + VideoMemSize = (32 << 20); /*32M */ + break; + } + } else { + switch (FBSize) { + case 0x00001000: + VideoMemSize = (8 << 20); /*8M */ + break; + + case 0x00002000: + VideoMemSize = (16 << 20); /*16M */ + break; + + case 0x00003000: + VideoMemSize = (32 << 20); /*32M */ + break; + + case 0x00004000: + VideoMemSize = (64 << 20); /*64M */ + break; + + case 0x00005000: + VideoMemSize = (128 << 20); /*128M */ + break; + + case 0x00006000: + VideoMemSize = (256 << 20); /*256M */ + break; + + case 0x00007000: /* Only on VX855/875 */ + VideoMemSize = (512 << 20); /*512M */ + break; + + default: + VideoMemSize = (32 << 20); /*32M */ + break; + } + } + + return VideoMemSize; +} + + +/* + * Figure out and map our MMIO regions. + */ +static int __devinit via_pci_setup_mmio(struct viafb_dev *vdev) +{ + /* + * Hook up to the device registers. + */ + vdev->engine_start = pci_resource_start(vdev->pdev, 1); + vdev->engine_len = pci_resource_len(vdev->pdev, 1); + /* If this fails, others will notice later */ + vdev->engine_mmio = ioremap_nocache(vdev->engine_start, + vdev->engine_len); + + /* + * Likewise with I/O memory. + */ + vdev->fbmem_start = pci_resource_start(vdev->pdev, 0); + vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type); + if (vdev->fbmem_len < 0) + return vdev->fbmem_len; + vdev->fbmem = ioremap_nocache(vdev->fbmem_start, vdev->fbmem_len); + if (vdev->fbmem == NULL) + return -ENOMEM; + return 0; +} + +static void __devexit via_pci_teardown_mmio(struct viafb_dev *vdev) +{ + iounmap(vdev->fbmem); + iounmap(vdev->engine_mmio); +} + static int __devinit via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -32,23 +198,35 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, ret = pci_enable_device(pdev); if (ret) return ret; + /* + * Global device initialization. + */ + memset(&global_dev, 0, sizeof(global_dev)); + global_dev.pdev = pdev; + global_dev.chip_type = ent->driver_data; + spin_lock_init(&global_dev.reg_lock); + ret = via_pci_setup_mmio(&global_dev); + if (ret) + goto out_disable; /* * Create the I2C busses. Bailing out on failure seems extreme, * but that's what the code did before. */ ret = viafb_create_i2c_busses(adap_configs); if (ret) - goto out_disable; + goto out_teardown; /* * Set up the framebuffer. */ - ret = via_fb_pci_probe(pdev, ent); + ret = via_fb_pci_probe(&global_dev); if (ret) goto out_i2c; return 0; out_i2c: viafb_delete_i2c_busses(); +out_teardown: + via_pci_teardown_mmio(&global_dev); out_disable: pci_disable_device(pdev); return ret; @@ -58,6 +236,7 @@ static void __devexit via_pci_remove(struct pci_dev *pdev) { viafb_delete_i2c_busses(); via_fb_pci_remove(pdev); + via_pci_teardown_mmio(&global_dev); pci_disable_device(pdev); } diff --git a/drivers/video/via/via-core.h b/drivers/video/via/via-core.h index 1c2fb06b77ae..d004290dc8f1 100644 --- a/drivers/video/via/via-core.h +++ b/drivers/video/via/via-core.h @@ -22,6 +22,9 @@ #ifndef __VIA_CORE_H__ #define __VIA_CORE_H__ +#include +#include + /* * A description of each known serial I2C/GPIO port. */ @@ -49,7 +52,38 @@ enum viafb_i2c_adap { struct via_port_cfg { enum via_port_type type; enum via_port_mode mode; - u_int16_t io_port; - u_int8_t ioport_index; + u16 io_port; + u8 ioport_index; }; + +/* + * This is the global viafb "device" containing stuff needed by + * all subdevs. + */ +struct viafb_dev { + struct pci_dev *pdev; + int chip_type; + /* + * Spinlock for access to device registers. Not yet + * globally used. + */ + spinlock_t reg_lock; + /* + * The framebuffer MMIO region. Little, if anything, touches + * this memory directly, and certainly nothing outside of the + * framebuffer device itself. We *do* have to be able to allocate + * chunks of this memory for other devices, though. + */ + unsigned long fbmem_start; + long fbmem_len; + void __iomem *fbmem; + /* + * The MMIO region for device registers. + */ + unsigned long engine_start; + unsigned long engine_len; + void __iomem *engine_mmio; + +}; + #endif /* __VIA_CORE_H__ */ diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index 478829281562..bcf2fe61a6ec 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -19,6 +19,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "via-core.h" +#include "via_i2c.h" #include "global.h" /* diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 17a874f6ea1c..70ed71facd87 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -24,6 +24,7 @@ #include #define _MASTER_FILE +#include "via-core.h" #include "global.h" static char *viafb_name = "Via"; @@ -220,7 +221,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var, /* Adjust var according to our driver's own table */ viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry); if (info->var.accel_flags & FB_ACCELF_TEXT && - !ppar->shared->engine_mmio) + !ppar->shared->vdev->engine_mmio) info->var.accel_flags = 0; return 0; @@ -695,7 +696,7 @@ static void viafb_fillrect(struct fb_info *info, rop = 0xF0; DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n"); - if (shared->hw_bitblt(shared->engine_mmio, VIA_BITBLT_FILL, + if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_FILL, rect->width, rect->height, info->var.bits_per_pixel, viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy, NULL, 0, 0, 0, 0, fg_color, 0, rop)) @@ -717,7 +718,7 @@ static void viafb_copyarea(struct fb_info *info, return; DEBUG_MSG(KERN_DEBUG "viafb 2D engine: copyarea\n"); - if (shared->hw_bitblt(shared->engine_mmio, VIA_BITBLT_COLOR, + if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_COLOR, area->width, area->height, info->var.bits_per_pixel, viapar->vram_addr, info->fix.line_length, area->dx, area->dy, NULL, viapar->vram_addr, info->fix.line_length, @@ -754,7 +755,7 @@ static void viafb_imageblit(struct fb_info *info, op = VIA_BITBLT_COLOR; DEBUG_MSG(KERN_DEBUG "viafb 2D engine: imageblit\n"); - if (shared->hw_bitblt(shared->engine_mmio, op, + if (shared->hw_bitblt(shared->vdev->engine_mmio, op, image->width, image->height, info->var.bits_per_pixel, viapar->vram_addr, info->fix.line_length, image->dx, image->dy, (u32 *)image->data, 0, 0, 0, 0, fg_color, bg_color, 0)) @@ -764,7 +765,7 @@ static void viafb_imageblit(struct fb_info *info, static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) { struct viafb_par *viapar = info->par; - void __iomem *engine = viapar->shared->engine_mmio; + void __iomem *engine = viapar->shared->vdev->engine_mmio; u32 temp, xx, yy, bg_color = 0, fg_color = 0, chip_name = viapar->shared->chip_info.gfx_chip_name; int i, j = 0, cur_size = 64; @@ -1732,8 +1733,7 @@ static int parse_mode(const char *str, u32 *xres, u32 *yres) } -int __devinit via_fb_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +int __devinit via_fb_pci_probe(struct viafb_dev *vdev) { u32 default_xres, default_yres; struct VideoModeTable *vmode_entry; @@ -1750,7 +1750,7 @@ int __devinit via_fb_pci_probe(struct pci_dev *pdev, */ viafbinfo = framebuffer_alloc(viafb_par_length + ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8), - &pdev->dev); + &vdev->pdev->dev); if (!viafbinfo) { printk(KERN_ERR"Could not allocate memory for viafb_info.\n"); return -ENOMEM; @@ -1758,6 +1758,7 @@ int __devinit via_fb_pci_probe(struct pci_dev *pdev, viaparinfo = (struct viafb_par *)viafbinfo->par; viaparinfo->shared = viafbinfo->par + viafb_par_length; + viaparinfo->shared->vdev = vdev; viaparinfo->vram_addr = 0; viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info; viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info; @@ -1765,7 +1766,6 @@ int __devinit via_fb_pci_probe(struct pci_dev *pdev, &viaparinfo->shared->lvds_setting_info2; viaparinfo->crt_setting_info = &viaparinfo->shared->crt_setting_info; viaparinfo->chip_info = &viaparinfo->shared->chip_info; - spin_lock_init(&viaparinfo->reg_lock); if (viafb_dual_fb) viafb_SAMM_ON = 1; @@ -1776,25 +1776,20 @@ int __devinit via_fb_pci_probe(struct pci_dev *pdev, if (!viafb_SAMM_ON) viafb_dual_fb = 0; - viafb_init_chip_info(pdev, ent); - viaparinfo->fbmem = pci_resource_start(pdev, 0); - viaparinfo->memsize = viafb_get_fb_size_from_pci(); - if (viaparinfo->memsize < 0) { - rc = viaparinfo->memsize; - goto out_fb_release; - } + viafb_init_chip_info(vdev->chip_type); + /* + * The framebuffer will have been successfully mapped by + * the core (or we'd not be here), but we still need to + * set up our own accounting. + */ + viaparinfo->fbmem = vdev->fbmem_start; + viaparinfo->memsize = vdev->fbmem_len; viaparinfo->fbmem_free = viaparinfo->memsize; viaparinfo->fbmem_used = 0; - viafbinfo->screen_base = ioremap_nocache(viaparinfo->fbmem, - viaparinfo->memsize); - if (!viafbinfo->screen_base) { - printk(KERN_ERR "ioremap of fbmem failed\n"); - rc = -ENOMEM; - goto out_fb_release; - } + viafbinfo->screen_base = vdev->fbmem; - viafbinfo->fix.mmio_start = pci_resource_start(pdev, 1); - viafbinfo->fix.mmio_len = pci_resource_len(pdev, 1); + viafbinfo->fix.mmio_start = vdev->engine_start; + viafbinfo->fix.mmio_len = vdev->engine_len; viafbinfo->node = 0; viafbinfo->fbops = &viafb_ops; viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; @@ -1862,12 +1857,13 @@ int __devinit via_fb_pci_probe(struct pci_dev *pdev, viafbinfo->var = default_var; if (viafb_dual_fb) { - viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev); + viafbinfo1 = framebuffer_alloc(viafb_par_length, + &vdev->pdev->dev); if (!viafbinfo1) { printk(KERN_ERR "allocate the second framebuffer struct error\n"); rc = -ENOMEM; - goto out_unmap_screen; + goto out_fb_release; } viaparinfo1 = viafbinfo1->par; memcpy(viaparinfo1, viaparinfo, viafb_par_length); @@ -1958,8 +1954,6 @@ out_dealloc_cmap: out_fb1_release: if (viafbinfo1) framebuffer_release(viafbinfo1); -out_unmap_screen: - iounmap(viafbinfo->screen_base); out_fb_release: framebuffer_release(viafbinfo); return rc; @@ -1972,8 +1966,6 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev) unregister_framebuffer(viafbinfo); if (viafb_dual_fb) unregister_framebuffer(viafbinfo1); - iounmap((void *)viafbinfo->screen_base); - iounmap(viaparinfo->shared->engine_mmio); framebuffer_release(viafbinfo); if (viafb_dual_fb) diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h index 5604f27eb74e..52a35fabba91 100644 --- a/drivers/video/via/viafbdev.h +++ b/drivers/video/via/viafbdev.h @@ -30,7 +30,6 @@ #include "share.h" #include "chip.h" #include "hw.h" -#include "via_i2c.h" #define VERSION_MAJOR 2 #define VERSION_KERNEL 6 /* For kernel 2.6 */ @@ -42,6 +41,7 @@ struct viafb_shared { struct proc_dir_entry *proc_entry; /*viafb proc entry */ + struct viafb_dev *vdev; /* Global dev info */ /* All the information will be needed to set engine */ struct tmds_setting_information tmds_setting_info; @@ -51,7 +51,6 @@ struct viafb_shared { struct chip_information chip_info; /* hardware acceleration stuff */ - void __iomem *engine_mmio; u32 cursor_vram_addr; u32 vq_vram_addr; /* virtual queue address in video ram */ int (*hw_bitblt)(void __iomem *engine, u8 op, u32 width, u32 height, @@ -72,14 +71,6 @@ struct viafb_par { struct viafb_shared *shared; - /* - * (jc) I believe one should use locking to protect against - * concurrent access to the device ports and registers. Thus, - * this lock. Use of it is *far* from universal, though... - * someday... - */ - spinlock_t reg_lock; - /* All the information will be needed to set engine */ /* depreciated, use the ones in shared directly */ struct tmds_setting_information *tmds_setting_info; @@ -107,7 +98,7 @@ u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information *plvds_chip_info, struct IODATA io_data); -int via_fb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent); +int via_fb_pci_probe(struct viafb_dev *vdev); void via_fb_pci_remove(struct pci_dev *pdev); /* Temporary */ int viafb_init(void); diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c index 4589c6e73c5d..e9f3661d6b3f 100644 --- a/drivers/video/via/vt1636.c +++ b/drivers/video/via/vt1636.c @@ -19,6 +19,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "via-core.h" +#include "via_i2c.h" #include "global.h" u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information -- cgit v1.2.3 From 7e0de022680f7899d33141f3ab5724a704f5669a Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Tue, 1 Dec 2009 20:39:57 -0700 Subject: viafb: add a driver for GPIO lines This is a simple gpiolib driver giving access to the GPIO lines in the VIA framebuffer system. A simple mechanism exists for switching lines between GPIO and I2C, but it's only compile-time for now. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/Kconfig | 2 + drivers/video/via/Makefile | 5 +- drivers/video/via/via-core.c | 7 ++ drivers/video/via/via-gpio.c | 268 +++++++++++++++++++++++++++++++++++++++++++ drivers/video/via/via-gpio.h | 15 +++ 5 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 drivers/video/via/via-gpio.c create mode 100644 drivers/video/via/via-gpio.h (limited to 'drivers/video') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 6e16244f3ed1..22c1662de964 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1511,6 +1511,7 @@ config FB_VIA select FB_CFB_IMAGEBLIT select I2C_ALGOBIT select I2C + select GPIOLIB help This is the frame buffer device driver for Graphics chips of VIA UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/ @@ -1520,6 +1521,7 @@ config FB_VIA To compile this driver as a module, choose M here: the module will be called viafb. + config FB_NEOMAGIC tristate "NeoMagic display support" depends on FB && PCI diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile index aec3f8b24a96..8c42a42c3dbb 100644 --- a/drivers/video/via/Makefile +++ b/drivers/video/via/Makefile @@ -4,4 +4,7 @@ obj-$(CONFIG_FB_VIA) += viafb.o -viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o via-core.o +viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \ + via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o \ + via-core.o via-gpio.o + diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index b77cd5c2fc96..806237e8b4a4 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c @@ -9,6 +9,7 @@ */ #include "via-core.h" #include "via_i2c.h" +#include "via-gpio.h" #include "global.h" #include @@ -221,6 +222,11 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, ret = via_fb_pci_probe(&global_dev); if (ret) goto out_i2c; + /* + * Create the GPIOs. We continue whether or not this succeeds; + * the framebuffer might be useful even without GPIO ports. + */ + ret = viafb_create_gpios(&global_dev, adap_configs); return 0; out_i2c: @@ -234,6 +240,7 @@ out_disable: static void __devexit via_pci_remove(struct pci_dev *pdev) { + viafb_destroy_gpios(); viafb_delete_i2c_busses(); via_fb_pci_remove(pdev); via_pci_teardown_mmio(&global_dev); diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c new file mode 100644 index 000000000000..e119d2103730 --- /dev/null +++ b/drivers/video/via/via-gpio.c @@ -0,0 +1,268 @@ +/* + * Support for viafb GPIO ports. + * + * Copyright 2009 Jonathan Corbet + * Distributable under version 2 of the GNU General Public License. + */ + +#include +#include +#include "via-core.h" +#include "via-gpio.h" +#include "global.h" + +/* + * The ports we know about. Note that the port-25 gpios are not + * mentioned in the datasheet. + */ + +struct viafb_gpio { + char *vg_name; /* Data sheet name */ + u16 vg_io_port; + u8 vg_port_index; + int vg_mask_shift; +}; + +static struct viafb_gpio viafb_all_gpios[] = { + { + .vg_name = "VGPIO0", /* Guess - not in datasheet */ + .vg_io_port = VIASR, + .vg_port_index = 0x25, + .vg_mask_shift = 1 + }, + { + .vg_name = "VGPIO1", + .vg_io_port = VIASR, + .vg_port_index = 0x25, + .vg_mask_shift = 0 + }, + { + .vg_name = "VGPIO2", /* aka DISPCLKI0 */ + .vg_io_port = VIASR, + .vg_port_index = 0x2c, + .vg_mask_shift = 1 + }, + { + .vg_name = "VGPIO3", /* aka DISPCLKO0 */ + .vg_io_port = VIASR, + .vg_port_index = 0x2c, + .vg_mask_shift = 0 + }, + { + .vg_name = "VGPIO4", /* DISPCLKI1 */ + .vg_io_port = VIASR, + .vg_port_index = 0x3d, + .vg_mask_shift = 1 + }, + { + .vg_name = "VGPIO5", /* DISPCLKO1 */ + .vg_io_port = VIASR, + .vg_port_index = 0x3d, + .vg_mask_shift = 0 + }, +}; + +#define VIAFB_NUM_GPIOS ARRAY_SIZE(viafb_all_gpios) + +/* + * This structure controls the active GPIOs, which may be a subset + * of those which are known. + */ + +struct viafb_gpio_cfg { + struct gpio_chip gpio_chip; + struct viafb_dev *vdev; + struct viafb_gpio *active_gpios[VIAFB_NUM_GPIOS]; + char *gpio_names[VIAFB_NUM_GPIOS]; +}; + +/* + * GPIO access functions + */ +static void via_gpio_set(struct gpio_chip *chip, unsigned int nr, + int value) +{ + struct viafb_gpio_cfg *cfg = container_of(chip, + struct viafb_gpio_cfg, + gpio_chip); + u8 reg; + struct viafb_gpio *gpio; + unsigned long flags; + + spin_lock_irqsave(&cfg->vdev->reg_lock, flags); + gpio = cfg->active_gpios[nr]; + reg = viafb_read_reg(VIASR, gpio->vg_port_index); + reg |= 0x40 << gpio->vg_mask_shift; /* output enable */ + if (value) + reg |= 0x10 << gpio->vg_mask_shift; + else + reg &= ~(0x10 << gpio->vg_mask_shift); + viafb_write_reg(gpio->vg_port_index, VIASR, reg); + spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags); +} + +static int via_gpio_dir_out(struct gpio_chip *chip, unsigned int nr, + int value) +{ + via_gpio_set(chip, nr, value); + return 0; +} + +/* + * Set the input direction. I'm not sure this is right; we should + * be able to do input without disabling output. + */ +static int via_gpio_dir_input(struct gpio_chip *chip, unsigned int nr) +{ + struct viafb_gpio_cfg *cfg = container_of(chip, + struct viafb_gpio_cfg, + gpio_chip); + struct viafb_gpio *gpio; + unsigned long flags; + + spin_lock_irqsave(&cfg->vdev->reg_lock, flags); + gpio = cfg->active_gpios[nr]; + viafb_write_reg_mask(gpio->vg_port_index, VIASR, 0, + 0x40 << gpio->vg_mask_shift); + spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags); + return 0; +} + +static int via_gpio_get(struct gpio_chip *chip, unsigned int nr) +{ + struct viafb_gpio_cfg *cfg = container_of(chip, + struct viafb_gpio_cfg, + gpio_chip); + u8 reg; + struct viafb_gpio *gpio; + unsigned long flags; + + spin_lock_irqsave(&cfg->vdev->reg_lock, flags); + gpio = cfg->active_gpios[nr]; + reg = viafb_read_reg(VIASR, gpio->vg_port_index); + spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags); + return reg & (0x04 << gpio->vg_mask_shift); +} + + +static struct viafb_gpio_cfg gpio_config = { + .gpio_chip = { + .label = "VIAFB onboard GPIO", + .owner = THIS_MODULE, + .direction_output = via_gpio_dir_out, + .set = via_gpio_set, + .direction_input = via_gpio_dir_input, + .get = via_gpio_get, + .base = -1, + .ngpio = 0, + .can_sleep = 0 + } +}; + +/* + * Manage the software enable bit. + */ +static void viafb_gpio_enable(struct viafb_gpio *gpio) +{ + viafb_write_reg_mask(gpio->vg_port_index, VIASR, 0x02, 0x02); +} + +static void viafb_gpio_disable(struct viafb_gpio *gpio) +{ + viafb_write_reg_mask(gpio->vg_port_index, VIASR, 0, 0x02); +} + + + + +int viafb_create_gpios(struct viafb_dev *vdev, + const struct via_port_cfg *port_cfg) +{ + int i, ngpio = 0, ret; + struct viafb_gpio *gpio; + unsigned long flags; + + /* + * Set up entries for all GPIOs which have been configured to + * operate as such (as opposed to as i2c ports). + */ + for (i = 0; i < VIAFB_NUM_PORTS; i++) { + if (port_cfg[i].mode != VIA_MODE_GPIO) + continue; + for (gpio = viafb_all_gpios; + gpio < viafb_all_gpios + VIAFB_NUM_GPIOS; gpio++) + if (gpio->vg_port_index == port_cfg[i].ioport_index) { + gpio_config.active_gpios[ngpio] = gpio; + gpio_config.gpio_names[ngpio] = gpio->vg_name; + ngpio++; + } + } + gpio_config.gpio_chip.ngpio = ngpio; + gpio_config.gpio_chip.names = gpio_config.gpio_names; + gpio_config.vdev = vdev; + if (ngpio == 0) { + printk(KERN_INFO "viafb: no GPIOs configured\n"); + return 0; + } + /* + * Enable the ports. They come in pairs, with a single + * enable bit for both. + */ + spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags); + for (i = 0; i < ngpio; i += 2) + viafb_gpio_enable(gpio_config.active_gpios[i]); + spin_unlock_irqrestore(&gpio_config.vdev->reg_lock, flags); + /* + * Get registered. + */ + gpio_config.gpio_chip.base = -1; /* Dynamic */ + ret = gpiochip_add(&gpio_config.gpio_chip); + if (ret) { + printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret); + gpio_config.gpio_chip.ngpio = 0; + } + return ret; +/* Port enable ? */ +} + + +int viafb_destroy_gpios(void) +{ + unsigned long flags; + int ret = 0, i; + + spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags); + /* + * Get unregistered. + */ + if (gpio_config.gpio_chip.ngpio > 0) { + ret = gpiochip_remove(&gpio_config.gpio_chip); + if (ret) { /* Somebody still using it? */ + printk(KERN_ERR "Viafb: GPIO remove failed\n"); + goto out; + } + } + /* + * Disable the ports. + */ + for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2) + viafb_gpio_disable(gpio_config.active_gpios[i]); + gpio_config.gpio_chip.ngpio = 0; +out: + spin_unlock_irqrestore(&gpio_config.vdev->reg_lock, flags); + return ret; +} + +/* + * Look up a specific gpio and return the number it was assigned. + */ +int viafb_gpio_lookup(const char *name) +{ + int i; + + for (i = 0; i < gpio_config.gpio_chip.ngpio; i++) + if (!strcmp(name, gpio_config.active_gpios[i]->vg_name)) + return gpio_config.gpio_chip.base + i; + return -1; +} +EXPORT_SYMBOL_GPL(viafb_gpio_lookup); diff --git a/drivers/video/via/via-gpio.h b/drivers/video/via/via-gpio.h new file mode 100644 index 000000000000..7b53f966eb4b --- /dev/null +++ b/drivers/video/via/via-gpio.h @@ -0,0 +1,15 @@ +/* + * Support for viafb GPIO ports. + * + * Copyright 2009 Jonathan Corbet + * Distributable under version 2 of the GNU General Public License. + */ + +#ifndef __VIA_GPIO_H__ +#define __VIA_GPIO_H__ + +extern int viafb_create_gpios(struct viafb_dev *vdev, + const struct via_port_cfg *port_cfg); +extern int viafb_destroy_gpios(void); +extern int viafb_gpio_lookup(const char *name); +#endif -- cgit v1.2.3 From c389874805a6849e3e347fc0e13fa170d80840c1 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sat, 17 Apr 2010 19:44:51 +0000 Subject: viafb: package often used basic io functions This patch puts redesigned versions of the basic io functions that are used overall the driver in an extra header. It is prefixed with via_ as no framebuffer dependend stuff is in there. They were inlined as they are really simple which reduced the module size about 2.5%. The parameter order of read and write was fixed as it really doesn't make sense to change the order as they are parts of the same address and not source and destination. Wrapper which use the new functions were added to hw.h to replicate the old interface and avoid changing all old code. [jc: added one comment] Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/hw.c | 22 ------------------ drivers/video/via/hw.h | 8 ++++--- drivers/video/via/via_io.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 25 deletions(-) create mode 100644 drivers/video/via/via_io.h (limited to 'drivers/video') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index f2425ae228ae..805151f48ea9 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -537,18 +537,6 @@ static void device_on(void); static void enable_second_display_channel(void); static void disable_second_display_channel(void); -void viafb_write_reg(u8 index, u16 io_port, u8 data) -{ - outb(index, io_port); - outb(data, io_port + 1); - /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, data); */ -} -u8 viafb_read_reg(int io_port, u8 index) -{ - outb(index, io_port); - return inb(io_port + 1); -} - void viafb_lock_crt(void) { viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7); @@ -560,16 +548,6 @@ void viafb_unlock_crt(void) viafb_write_reg_mask(CR47, VIACR, 0, BIT0); } -void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask) -{ - u8 tmp; - - outb(index, io_port); - tmp = inb(io_port + 1); - outb((data & mask) | (tmp & (~mask)), io_port + 1); - /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, tmp); */ -} - void write_dac_reg(u8 index, u8 r, u8 g, u8 b) { outb(index, LUT_INDEX_WRITE); diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index d248f4dc12ec..23c319010913 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -24,6 +24,11 @@ #include "viamode.h" #include "global.h" +#include "via_io.h" + +#define viafb_read_reg(p, i) via_read_reg(p, i) +#define viafb_write_reg(i, p, d) via_write_reg(p, i, d) +#define viafb_write_reg_mask(i, p, d, m) via_write_reg_mask(p, i, d, m) /*************************************************** * Definition IGA1 Design Method of CRTC Registers * @@ -870,7 +875,6 @@ extern int viafb_LCD_ON; extern int viafb_DVI_ON; extern int viafb_hotplug; -void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask); void viafb_set_output_path(int device, int set_iga, int output_interface); @@ -885,8 +889,6 @@ void viafb_crt_disable(void); void viafb_crt_enable(void); void init_ad9389(void); /* Access I/O Function */ -void viafb_write_reg(u8 index, u16 io_port, u8 data); -u8 viafb_read_reg(int io_port, u8 index); void viafb_lock_crt(void); void viafb_unlock_crt(void); void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga); diff --git a/drivers/video/via/via_io.h b/drivers/video/via/via_io.h new file mode 100644 index 000000000000..e1c1093def00 --- /dev/null +++ b/drivers/video/via/via_io.h @@ -0,0 +1,58 @@ +/* + * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. + * Copyright 2010 Florian Tobias Schandinat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; + * either version 2, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE.See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +/* + * basic io functions + */ + +#ifndef __VIA_IO_H__ +#define __VIA_IO_H__ + +#include +#include + +/* + * Indexed port operations. Note that these are all multi-op + * functions; every invocation will be racy if you're not holding + * reg_lock. + */ +static inline u8 via_read_reg(u16 port, u8 index) +{ + outb(index, port); + return inb(port + 1); +} + +static inline void via_write_reg(u16 port, u8 index, u8 data) +{ + outb(index, port); + outb(data, port + 1); +} + +static inline void via_write_reg_mask(u16 port, u8 index, u8 data, u8 mask) +{ + u8 old; + + outb(index, port); + old = inb(port + 1); + outb((data & mask) | (old & ~mask), port + 1); +} + +#endif /* __VIA_IO_H__ */ -- cgit v1.2.3 From 75b035ace904761b8a340b524533a36e37313b29 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Thu, 22 Apr 2010 14:36:04 -0600 Subject: viafb: Convert GPIO and i2c to the new indexed port ops Also add low-level locking to the i2c driver. Signed-off-by: Jonathan Corbet --- drivers/video/via/via-core.c | 2 +- drivers/video/via/via-gpio.c | 14 +++++++------- drivers/video/via/via_i2c.c | 46 ++++++++++++++++++++++++++++---------------- drivers/video/via/via_i2c.h | 2 +- 4 files changed, 38 insertions(+), 26 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index 806237e8b4a4..a1b5dae285a4 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c @@ -213,7 +213,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, * Create the I2C busses. Bailing out on failure seems extreme, * but that's what the code did before. */ - ret = viafb_create_i2c_busses(adap_configs); + ret = viafb_create_i2c_busses(&global_dev, adap_configs); if (ret) goto out_teardown; /* diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c index e119d2103730..6b361177bf03 100644 --- a/drivers/video/via/via-gpio.c +++ b/drivers/video/via/via-gpio.c @@ -91,13 +91,13 @@ static void via_gpio_set(struct gpio_chip *chip, unsigned int nr, spin_lock_irqsave(&cfg->vdev->reg_lock, flags); gpio = cfg->active_gpios[nr]; - reg = viafb_read_reg(VIASR, gpio->vg_port_index); + reg = via_read_reg(VIASR, gpio->vg_port_index); reg |= 0x40 << gpio->vg_mask_shift; /* output enable */ if (value) reg |= 0x10 << gpio->vg_mask_shift; else reg &= ~(0x10 << gpio->vg_mask_shift); - viafb_write_reg(gpio->vg_port_index, VIASR, reg); + via_write_reg(VIASR, gpio->vg_port_index, reg); spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags); } @@ -122,8 +122,8 @@ static int via_gpio_dir_input(struct gpio_chip *chip, unsigned int nr) spin_lock_irqsave(&cfg->vdev->reg_lock, flags); gpio = cfg->active_gpios[nr]; - viafb_write_reg_mask(gpio->vg_port_index, VIASR, 0, - 0x40 << gpio->vg_mask_shift); + via_write_reg_mask(VIASR, gpio->vg_port_index, 0, + 0x40 << gpio->vg_mask_shift); spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags); return 0; } @@ -139,7 +139,7 @@ static int via_gpio_get(struct gpio_chip *chip, unsigned int nr) spin_lock_irqsave(&cfg->vdev->reg_lock, flags); gpio = cfg->active_gpios[nr]; - reg = viafb_read_reg(VIASR, gpio->vg_port_index); + reg = via_read_reg(VIASR, gpio->vg_port_index); spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags); return reg & (0x04 << gpio->vg_mask_shift); } @@ -164,12 +164,12 @@ static struct viafb_gpio_cfg gpio_config = { */ static void viafb_gpio_enable(struct viafb_gpio *gpio) { - viafb_write_reg_mask(gpio->vg_port_index, VIASR, 0x02, 0x02); + via_write_reg_mask(VIASR, gpio->vg_port_index, 0x02, 0x02); } static void viafb_gpio_disable(struct viafb_gpio *gpio) { - viafb_write_reg_mask(gpio->vg_port_index, VIASR, 0, 0x02); + via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02); } diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index bcf2fe61a6ec..116fd3e62934 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -29,14 +29,16 @@ */ #define VIAFB_NUM_I2C 5 static struct via_i2c_stuff via_i2c_par[VIAFB_NUM_I2C]; +struct viafb_dev *i2c_vdev; /* Passed in from core */ static void via_i2c_setscl(void *data, int state) { u8 val; struct via_port_cfg *adap_data = data; + unsigned long flags; - val = viafb_read_reg(adap_data->io_port, - adap_data->ioport_index) & 0xF0; + spin_lock_irqsave(&i2c_vdev->reg_lock, flags); + val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0; if (state) val |= 0x20; else @@ -51,35 +53,44 @@ static void via_i2c_setscl(void *data, int state) default: DEBUG_MSG("viafb_i2c: specify wrong i2c type.\n"); } - viafb_write_reg(adap_data->ioport_index, - adap_data->io_port, val); + via_write_reg(adap_data->io_port, adap_data->ioport_index, val); + spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); } static int via_i2c_getscl(void *data) { struct via_port_cfg *adap_data = data; - - if (viafb_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08) - return 1; - return 0; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&i2c_vdev->reg_lock, flags); + if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08) + ret = 1; + spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); + return ret; } static int via_i2c_getsda(void *data) { struct via_port_cfg *adap_data = data; - - if (viafb_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04) - return 1; - return 0; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&i2c_vdev->reg_lock, flags); + if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04) + ret = 1; + spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); + return ret; } static void via_i2c_setsda(void *data, int state) { u8 val; struct via_port_cfg *adap_data = data; + unsigned long flags; - val = viafb_read_reg(adap_data->io_port, - adap_data->ioport_index) & 0xF0; + spin_lock_irqsave(&i2c_vdev->reg_lock, flags); + val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0; if (state) val |= 0x10; else @@ -94,8 +105,8 @@ static void via_i2c_setsda(void *data, int state) default: DEBUG_MSG("viafb_i2c: specify wrong i2c type.\n"); } - viafb_write_reg(adap_data->ioport_index, - adap_data->io_port, val); + via_write_reg(adap_data->io_port, adap_data->ioport_index, val); + spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); } int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata) @@ -174,10 +185,11 @@ static int create_i2c_bus(struct i2c_adapter *adapter, return i2c_bit_add_bus(adapter); } -int viafb_create_i2c_busses(struct via_port_cfg *configs) +int viafb_create_i2c_busses(struct viafb_dev *dev, struct via_port_cfg *configs) { int i, ret; + i2c_vdev = dev; for (i = 0; i < VIAFB_NUM_PORTS; i++) { struct via_port_cfg *adap_cfg = configs++; struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i]; diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_i2c.h index 00932914b4ed..0685de9a0c7a 100644 --- a/drivers/video/via/via_i2c.h +++ b/drivers/video/via/via_i2c.h @@ -36,7 +36,7 @@ int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data); int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len); struct viafb_par; -int viafb_create_i2c_busses(struct via_port_cfg *cfg); +int viafb_create_i2c_busses(struct viafb_dev *vdev, struct via_port_cfg *cfg); void viafb_delete_i2c_busses(void); struct i2c_adapter *viafb_find_adapter(enum viafb_i2c_adap which); #endif /* __VIA_I2C_H__ */ -- cgit v1.2.3 From 7582eb9be85f35271fd2569681a88a5b243e9380 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Thu, 22 Apr 2010 17:39:34 -0600 Subject: viafb: Turn GPIO and i2c into proper platform devices Another step toward making this thing a real multifunction device driver. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/via-core.c | 91 ++++++++++++++++++++++++++++++++++++-------- drivers/video/via/via-core.h | 1 + drivers/video/via/via-gpio.c | 49 ++++++++++++++++-------- drivers/video/via/via-gpio.h | 5 +-- drivers/video/via/via_i2c.c | 29 ++++++++++++-- drivers/video/via/via_i2c.h | 6 +-- 6 files changed, 140 insertions(+), 41 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index a1b5dae285a4..5a78ef9cb382 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c @@ -190,6 +190,70 @@ static void __devexit via_pci_teardown_mmio(struct viafb_dev *vdev) iounmap(vdev->engine_mmio); } +/* + * Create our subsidiary devices. + */ +static struct viafb_subdev_info { + char *name; + struct platform_device *platdev; +} viafb_subdevs[] = { + { + .name = "viafb-gpio", + }, + { + .name = "viafb-i2c", + } +}; +#define N_SUBDEVS ARRAY_SIZE(viafb_subdevs) + +static int __devinit via_create_subdev(struct viafb_dev *vdev, + struct viafb_subdev_info *info) +{ + int ret; + + info->platdev = platform_device_alloc(info->name, -1); + if (!info->platdev) { + dev_err(&vdev->pdev->dev, "Unable to allocate pdev %s\n", + info->name); + return -ENOMEM; + } + info->platdev->dev.parent = &vdev->pdev->dev; + info->platdev->dev.platform_data = vdev; + ret = platform_device_add(info->platdev); + if (ret) { + dev_err(&vdev->pdev->dev, "Unable to add pdev %s\n", + info->name); + platform_device_put(info->platdev); + info->platdev = NULL; + } + return ret; +} + +static int __devinit via_setup_subdevs(struct viafb_dev *vdev) +{ + int i; + + /* + * Ignore return values. Even if some of the devices + * fail to be created, we'll still be able to use some + * of the rest. + */ + for (i = 0; i < N_SUBDEVS; i++) + via_create_subdev(vdev, viafb_subdevs + i); + return 0; +} + +static void __devexit via_teardown_subdevs(void) +{ + int i; + + for (i = 0; i < N_SUBDEVS; i++) + if (viafb_subdevs[i].platdev) { + viafb_subdevs[i].platdev->dev.platform_data = NULL; + platform_device_unregister(viafb_subdevs[i].platdev); + } +} + static int __devinit via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -205,33 +269,25 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, memset(&global_dev, 0, sizeof(global_dev)); global_dev.pdev = pdev; global_dev.chip_type = ent->driver_data; + global_dev.port_cfg = adap_configs; spin_lock_init(&global_dev.reg_lock); ret = via_pci_setup_mmio(&global_dev); if (ret) goto out_disable; /* - * Create the I2C busses. Bailing out on failure seems extreme, - * but that's what the code did before. + * Create our subdevices. Continue even if some things fail. */ - ret = viafb_create_i2c_busses(&global_dev, adap_configs); - if (ret) - goto out_teardown; + via_setup_subdevs(&global_dev); /* * Set up the framebuffer. */ ret = via_fb_pci_probe(&global_dev); if (ret) - goto out_i2c; - /* - * Create the GPIOs. We continue whether or not this succeeds; - * the framebuffer might be useful even without GPIO ports. - */ - ret = viafb_create_gpios(&global_dev, adap_configs); + goto out_subdevs; return 0; -out_i2c: - viafb_delete_i2c_busses(); -out_teardown: +out_subdevs: + via_teardown_subdevs(); via_pci_teardown_mmio(&global_dev); out_disable: pci_disable_device(pdev); @@ -240,8 +296,7 @@ out_disable: static void __devexit via_pci_remove(struct pci_dev *pdev) { - viafb_destroy_gpios(); - viafb_delete_i2c_busses(); + via_teardown_subdevs(); via_fb_pci_remove(pdev); via_pci_teardown_mmio(&global_dev); pci_disable_device(pdev); @@ -289,12 +344,16 @@ static int __init via_core_init(void) ret = viafb_init(); if (ret) return ret; + viafb_i2c_init(); + viafb_gpio_init(); return pci_register_driver(&via_driver); } static void __exit via_core_exit(void) { pci_unregister_driver(&via_driver); + viafb_gpio_exit(); + viafb_i2c_exit(); viafb_exit(); } diff --git a/drivers/video/via/via-core.h b/drivers/video/via/via-core.h index d004290dc8f1..ac89c2aa98b5 100644 --- a/drivers/video/via/via-core.h +++ b/drivers/video/via/via-core.h @@ -63,6 +63,7 @@ struct via_port_cfg { struct viafb_dev { struct pci_dev *pdev; int chip_type; + struct via_port_cfg *port_cfg; /* * Spinlock for access to device registers. Not yet * globally used. diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c index 6b361177bf03..44537be1f070 100644 --- a/drivers/video/via/via-gpio.c +++ b/drivers/video/via/via-gpio.c @@ -7,6 +7,7 @@ #include #include +#include #include "via-core.h" #include "via-gpio.h" #include "global.h" @@ -172,12 +173,27 @@ static void viafb_gpio_disable(struct viafb_gpio *gpio) via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02); } +/* + * Look up a specific gpio and return the number it was assigned. + */ +int viafb_gpio_lookup(const char *name) +{ + int i; + for (i = 0; i < gpio_config.gpio_chip.ngpio; i++) + if (!strcmp(name, gpio_config.active_gpios[i]->vg_name)) + return gpio_config.gpio_chip.base + i; + return -1; +} +EXPORT_SYMBOL_GPL(viafb_gpio_lookup); - -int viafb_create_gpios(struct viafb_dev *vdev, - const struct via_port_cfg *port_cfg) +/* + * Platform device stuff. + */ +static __devinit int viafb_gpio_probe(struct platform_device *platdev) { + struct viafb_dev *vdev = platdev->dev.platform_data; + struct via_port_cfg *port_cfg = vdev->port_cfg; int i, ngpio = 0, ret; struct viafb_gpio *gpio; unsigned long flags; @@ -222,11 +238,10 @@ int viafb_create_gpios(struct viafb_dev *vdev, gpio_config.gpio_chip.ngpio = 0; } return ret; -/* Port enable ? */ } -int viafb_destroy_gpios(void) +static int viafb_gpio_remove(struct platform_device *platdev) { unsigned long flags; int ret = 0, i; @@ -253,16 +268,20 @@ out: return ret; } -/* - * Look up a specific gpio and return the number it was assigned. - */ -int viafb_gpio_lookup(const char *name) +static struct platform_driver via_gpio_driver = { + .driver = { + .name = "viafb-gpio", + }, + .probe = viafb_gpio_probe, + .remove = viafb_gpio_remove, +}; + +int viafb_gpio_init(void) { - int i; + return platform_driver_register(&via_gpio_driver); +} - for (i = 0; i < gpio_config.gpio_chip.ngpio; i++) - if (!strcmp(name, gpio_config.active_gpios[i]->vg_name)) - return gpio_config.gpio_chip.base + i; - return -1; +void viafb_gpio_exit(void) +{ + platform_driver_unregister(&via_gpio_driver); } -EXPORT_SYMBOL_GPL(viafb_gpio_lookup); diff --git a/drivers/video/via/via-gpio.h b/drivers/video/via/via-gpio.h index 7b53f966eb4b..8281aea3dd6d 100644 --- a/drivers/video/via/via-gpio.h +++ b/drivers/video/via/via-gpio.h @@ -8,8 +8,7 @@ #ifndef __VIA_GPIO_H__ #define __VIA_GPIO_H__ -extern int viafb_create_gpios(struct viafb_dev *vdev, - const struct via_port_cfg *port_cfg); -extern int viafb_destroy_gpios(void); extern int viafb_gpio_lookup(const char *name); +extern int viafb_gpio_init(void); +extern void viafb_gpio_exit(void); #endif diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index 116fd3e62934..3ff60b280d88 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -19,6 +19,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include #include "via-core.h" #include "via_i2c.h" #include "global.h" @@ -185,11 +186,14 @@ static int create_i2c_bus(struct i2c_adapter *adapter, return i2c_bit_add_bus(adapter); } -int viafb_create_i2c_busses(struct viafb_dev *dev, struct via_port_cfg *configs) +static int viafb_i2c_probe(struct platform_device *platdev) { int i, ret; + struct via_port_cfg *configs; + + i2c_vdev = platdev->dev.platform_data; + configs = i2c_vdev->port_cfg; - i2c_vdev = dev; for (i = 0; i < VIAFB_NUM_PORTS; i++) { struct via_port_cfg *adap_cfg = configs++; struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i]; @@ -211,7 +215,7 @@ int viafb_create_i2c_busses(struct viafb_dev *dev, struct via_port_cfg *configs) return 0; } -void viafb_delete_i2c_busses(void) +static int viafb_i2c_remove(struct platform_device *platdev) { int i; @@ -224,4 +228,23 @@ void viafb_delete_i2c_busses(void) if (i2c_stuff->adapter.algo_data == &i2c_stuff->algo) i2c_del_adapter(&i2c_stuff->adapter); } + return 0; +} + +static struct platform_driver via_i2c_driver = { + .driver = { + .name = "viafb-i2c", + }, + .probe = viafb_i2c_probe, + .remove = viafb_i2c_remove, +}; + +int viafb_i2c_init(void) +{ + return platform_driver_register(&via_i2c_driver); +} + +void viafb_i2c_exit(void) +{ + platform_driver_unregister(&via_i2c_driver); } diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_i2c.h index 0685de9a0c7a..b2332cce9d18 100644 --- a/drivers/video/via/via_i2c.h +++ b/drivers/video/via/via_i2c.h @@ -35,8 +35,6 @@ int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata); int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data); int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len); -struct viafb_par; -int viafb_create_i2c_busses(struct viafb_dev *vdev, struct via_port_cfg *cfg); -void viafb_delete_i2c_busses(void); -struct i2c_adapter *viafb_find_adapter(enum viafb_i2c_adap which); +extern int viafb_i2c_init(void); +extern void viafb_i2c_exit(void); #endif /* __VIA_I2C_H__ */ -- cgit v1.2.3 From b052d7f81fdd352a5d89ef1ac37a2c77f219463b Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Mon, 28 Dec 2009 10:04:02 -0700 Subject: via: Do not attempt I/O on inactive I2C adapters If an adapter has been configured for GPIO (or off), we should not try to use it as an I2C port. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/via_i2c.c | 14 ++++++++++---- drivers/video/via/via_i2c.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index 3ff60b280d88..c88450ee62ba 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -115,6 +115,8 @@ int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata) u8 mm1[] = {0x00}; struct i2c_msg msgs[2]; + if (!via_i2c_par[adap].is_active) + return -ENODEV; *pdata = 0; msgs[0].flags = 0; msgs[1].flags = I2C_M_RD; @@ -130,6 +132,8 @@ int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data) u8 msg[2] = { index, data }; struct i2c_msg msgs; + if (!via_i2c_par[adap].is_active) + return -ENODEV; msgs.flags = 0; msgs.addr = slave_addr / 2; msgs.len = 2; @@ -142,6 +146,8 @@ int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len u8 mm1[] = {0x00}; struct i2c_msg msgs[2]; + if (!via_i2c_par[adap].is_active) + return -ENODEV; msgs[0].flags = 0; msgs[1].flags = I2C_M_RD; msgs[0].addr = msgs[1].addr = slave_addr / 2; @@ -198,18 +204,18 @@ static int viafb_i2c_probe(struct platform_device *platdev) struct via_port_cfg *adap_cfg = configs++; struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i]; + i2c_stuff->is_active = 0; if (adap_cfg->type == 0 || adap_cfg->mode != VIA_MODE_I2C) continue; - ret = create_i2c_bus(&i2c_stuff->adapter, &i2c_stuff->algo, adap_cfg, NULL); /* FIXME: PCIDEV */ if (ret < 0) { printk(KERN_ERR "viafb: cannot create i2c bus %u:%d\n", i, ret); - /* FIXME: properly release previous busses */ - return ret; + continue; /* Still try to make the rest */ } + i2c_stuff->is_active = 1; } return 0; @@ -225,7 +231,7 @@ static int viafb_i2c_remove(struct platform_device *platdev) * Only remove those entries in the array that we've * actually used (and thus initialized algo_data) */ - if (i2c_stuff->adapter.algo_data == &i2c_stuff->algo) + if (i2c_stuff->is_active) i2c_del_adapter(&i2c_stuff->adapter); } return 0; diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_i2c.h index b2332cce9d18..1d18e7d57b7f 100644 --- a/drivers/video/via/via_i2c.h +++ b/drivers/video/via/via_i2c.h @@ -26,6 +26,7 @@ struct via_i2c_stuff { u16 i2c_port; /* GPIO or I2C port */ + u16 is_active; /* Being used as I2C? */ struct i2c_adapter adapter; struct i2c_algo_bit_data algo; }; -- cgit v1.2.3 From b8f7e5d846387e3bcda35f3809856cf085740a24 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 23 Apr 2010 08:56:55 -0600 Subject: viafb: Introduce viafb_find_i2c_adapter() The camera driver will need this to look up a specific adapter. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/via_i2c.c | 13 +++++++++++++ drivers/video/via/via_i2c.h | 1 + 2 files changed, 14 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index c88450ee62ba..febc1dda69c1 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -157,6 +157,19 @@ int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2); } +/* + * Allow other viafb subdevices to look up a specific adapter + * by port name. + */ +struct i2c_adapter *viafb_find_i2c_adapter(enum viafb_i2c_adap which) +{ + struct via_i2c_stuff *stuff = &via_i2c_par[which]; + + return &stuff->adapter; +} +EXPORT_SYMBOL_GPL(viafb_find_i2c_adapter); + + static int create_i2c_bus(struct i2c_adapter *adapter, struct i2c_algo_bit_data *algo, struct via_port_cfg *adap_cfg, diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_i2c.h index 1d18e7d57b7f..44532e468c05 100644 --- a/drivers/video/via/via_i2c.h +++ b/drivers/video/via/via_i2c.h @@ -35,6 +35,7 @@ struct via_i2c_stuff { int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata); int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data); int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len); +struct i2c_adapter *viafb_find_i2c_adapter(enum viafb_i2c_adap which); extern int viafb_i2c_init(void); extern void viafb_i2c_exit(void); -- cgit v1.2.3 From 6b841edf572ad757f11013326b796e126f05a719 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Mon, 28 Dec 2009 10:22:53 -0700 Subject: via: Rationalize vt1636 detection The code was ugly and didn't check whether i2c operations were succeeding; make it a little better. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/vt1636.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c index e9f3661d6b3f..e5f802472883 100644 --- a/drivers/video/via/vt1636.c +++ b/drivers/video/via/vt1636.c @@ -167,26 +167,20 @@ bool viafb_lvds_identify_vt1636(u8 i2c_adapter) /* Sense VT1636 LVDS Transmiter */ viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr = - VT1636_LVDS_I2C_ADDR; + VT1636_LVDS_I2C_ADDR; /* Check vendor ID first: */ - viafb_i2c_readbyte(i2c_adapter, - (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr, - 0x00, &Buffer[0]); - viafb_i2c_readbyte(i2c_adapter, - (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr, - 0x01, &Buffer[1]); + if (viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, + 0x00, &Buffer[0])) + return false; + viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x01, &Buffer[1]); if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11))) return false; /* Check Chip ID: */ - viafb_i2c_readbyte(i2c_adapter, - (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr, - 0x02, &Buffer[0]); - viafb_i2c_readbyte(i2c_adapter, - (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr, - 0x03, &Buffer[1]); + viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x02, &Buffer[0]); + viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x03, &Buffer[1]); if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) { viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1636_LVDS; -- cgit v1.2.3 From 94dd1a856b23bd51dfebf68e6dd63cfd4d4fd5ae Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 23 Apr 2010 09:46:59 -0600 Subject: viafb: Add a simple interrupt management infrastructure The viafb device shares a single interrupt control register among several distinct subunits. This adds a simple layer for management of that register. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/via-core.c | 64 +++++++++++++++++++++++++++++++++++++++++++- drivers/video/via/via-core.h | 44 ++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index 5a78ef9cb382..701b95575747 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c @@ -34,6 +34,65 @@ static struct via_port_cfg adap_configs[] = { static struct viafb_dev global_dev; +/* + * Basic register access; spinlock required. + */ +static inline void viafb_mmio_write(int reg, u32 v) +{ + iowrite32(v, global_dev.engine_mmio + reg); +} + +static inline int viafb_mmio_read(int reg) +{ + return ioread32(global_dev.engine_mmio + reg); +} + +/* ---------------------------------------------------------------------- */ +/* + * Interrupt management. We have a single IRQ line for a lot of + * different functions, so we need to share it. The design here + * is that we don't want to reimplement the shared IRQ code here; + * we also want to avoid having contention for a single handler thread. + * So each subdev driver which needs interrupts just requests + * them directly from the kernel. We just have what's needed for + * overall access to the interrupt control register. + */ + +/* + * Which interrupts are enabled now? + */ +static u32 viafb_enabled_ints; + +static void viafb_int_init(void) +{ + viafb_enabled_ints = 0; + + viafb_mmio_write(VDE_INTERRUPT, 0); +} + +/* + * Allow subdevs to ask for specific interrupts to be enabled. These + * functions must be called with reg_lock held + */ +void viafb_irq_enable(u32 mask) +{ + viafb_enabled_ints |= mask; + viafb_mmio_write(VDE_INTERRUPT, viafb_enabled_ints | VDE_I_ENABLE); +} +EXPORT_SYMBOL_GPL(viafb_irq_enable); + +void viafb_irq_disable(u32 mask) +{ + viafb_enabled_ints &= ~mask; + if (viafb_enabled_ints == 0) + viafb_mmio_write(VDE_INTERRUPT, 0); /* Disable entirely */ + else + viafb_mmio_write(VDE_INTERRUPT, + viafb_enabled_ints | VDE_I_ENABLE); +} +EXPORT_SYMBOL_GPL(viafb_irq_disable); + + /* * Figure out how big our framebuffer memory is. Kind of ugly, * but evidently we can't trust the information found in the @@ -275,8 +334,10 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, if (ret) goto out_disable; /* - * Create our subdevices. Continue even if some things fail. + * Set up interrupts and create our subdevices. Continue even if + * some things fail. */ + viafb_int_init(); via_setup_subdevs(&global_dev); /* * Set up the framebuffer. @@ -284,6 +345,7 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, ret = via_fb_pci_probe(&global_dev); if (ret) goto out_subdevs; + return 0; out_subdevs: diff --git a/drivers/video/via/via-core.h b/drivers/video/via/via-core.h index ac89c2aa98b5..ba64b36d58e3 100644 --- a/drivers/video/via/via-core.h +++ b/drivers/video/via/via-core.h @@ -87,4 +87,48 @@ struct viafb_dev { }; +/* + * Interrupt management. + */ + +void viafb_irq_enable(u32 mask); +void viafb_irq_disable(u32 mask); + +/* + * The global interrupt control register and its bits. + */ +#define VDE_INTERRUPT 0x200 /* Video interrupt flags/masks */ +#define VDE_I_DVISENSE 0x00000001 /* DVI sense int status */ +#define VDE_I_VBLANK 0x00000002 /* Vertical blank status */ +#define VDE_I_MCCFI 0x00000004 /* MCE compl. frame int status */ +#define VDE_I_VSYNC 0x00000008 /* VGA VSYNC int status */ +#define VDE_I_DMA0DDONE 0x00000010 /* DMA 0 descr done */ +#define VDE_I_DMA0TDONE 0x00000020 /* DMA 0 transfer done */ +#define VDE_I_DMA1DDONE 0x00000040 /* DMA 1 descr done */ +#define VDE_I_DMA1TDONE 0x00000080 /* DMA 1 transfer done */ +#define VDE_I_C1AV 0x00000100 /* Cap Eng 1 act vid end */ +#define VDE_I_HQV0 0x00000200 /* First HQV engine */ +#define VDE_I_HQV1 0x00000400 /* Second HQV engine */ +#define VDE_I_HQV1EN 0x00000800 /* Second HQV engine enable */ +#define VDE_I_C0AV 0x00001000 /* Cap Eng 0 act vid end */ +#define VDE_I_C0VBI 0x00002000 /* Cap Eng 0 VBI end */ +#define VDE_I_C1VBI 0x00004000 /* Cap Eng 1 VBI end */ +#define VDE_I_VSYNC2 0x00008000 /* Sec. Disp. VSYNC */ +#define VDE_I_DVISNSEN 0x00010000 /* DVI sense enable */ +#define VDE_I_VSYNC2EN 0x00020000 /* Sec Disp VSYNC enable */ +#define VDE_I_MCCFIEN 0x00040000 /* MC comp frame int mask enable */ +#define VDE_I_VSYNCEN 0x00080000 /* VSYNC enable */ +#define VDE_I_DMA0DDEN 0x00100000 /* DMA 0 descr done enable */ +#define VDE_I_DMA0TDEN 0x00200000 /* DMA 0 trans done enable */ +#define VDE_I_DMA1DDEN 0x00400000 /* DMA 1 descr done enable */ +#define VDE_I_DMA1TDEN 0x00800000 /* DMA 1 trans done enable */ +#define VDE_I_C1AVEN 0x01000000 /* cap 1 act vid end enable */ +#define VDE_I_HQV0EN 0x02000000 /* First hqv engine enable */ +#define VDE_I_C1VBIEN 0x04000000 /* Cap 1 VBI end enable */ +#define VDE_I_LVDSSI 0x08000000 /* LVDS sense interrupt */ +#define VDE_I_C0AVEN 0x10000000 /* Cap 0 act vid end enable */ +#define VDE_I_C0VBIEN 0x20000000 /* Cap 0 VBI end enable */ +#define VDE_I_LVDSSIEN 0x40000000 /* LVDS Sense enable */ +#define VDE_I_ENABLE 0x80000000 /* Global interrupt enable */ + #endif /* __VIA_CORE_H__ */ -- cgit v1.2.3 From 3d28eb42c52a799c806082e6d856f634ed1db902 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 23 Apr 2010 10:04:12 -0600 Subject: viafb: Add a simple VX855 DMA engine driver This code provides a minimal amount of access to the DMA engine as needed by the camera driver. VX855 only; it's guaranteed not to work on other chipsets, so it won't try. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/via-core.c | 232 +++++++++++++++++++++++++++++++++++++++++++ drivers/video/via/via-core.h | 29 ++++++ 2 files changed, 261 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index 701b95575747..9929bb1549b6 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c @@ -13,6 +13,7 @@ #include "global.h" #include +#include #include /* @@ -92,7 +93,238 @@ void viafb_irq_disable(u32 mask) } EXPORT_SYMBOL_GPL(viafb_irq_disable); +/* ---------------------------------------------------------------------- */ +/* + * Access to the DMA engine. This currently provides what the camera + * driver needs (i.e. outgoing only) but is easily expandable if need + * be. + */ + +/* + * There are four DMA channels in the vx855. For now, we only + * use one of them, though. Most of the time, the DMA channel + * will be idle, so we keep the IRQ handler unregistered except + * when some subsystem has indicated an interest. + */ +static int viafb_dma_users; +static DECLARE_COMPLETION(viafb_dma_completion); +/* + * This mutex protects viafb_dma_users and our global interrupt + * registration state; it also serializes access to the DMA + * engine. + */ +static DEFINE_MUTEX(viafb_dma_lock); + +/* + * The VX855 DMA descriptor (used for s/g transfers) looks + * like this. + */ +struct viafb_vx855_dma_descr { + u32 addr_low; /* Low part of phys addr */ + u32 addr_high; /* High 12 bits of addr */ + u32 fb_offset; /* Offset into FB memory */ + u32 seg_size; /* Size, 16-byte units */ + u32 tile_mode; /* "tile mode" setting */ + u32 next_desc_low; /* Next descriptor addr */ + u32 next_desc_high; + u32 pad; /* Fill out to 64 bytes */ +}; + +/* + * Flags added to the "next descriptor low" pointers + */ +#define VIAFB_DMA_MAGIC 0x01 /* ??? Just has to be there */ +#define VIAFB_DMA_FINAL_SEGMENT 0x02 /* Final segment */ + +/* + * The completion IRQ handler. + */ +static irqreturn_t viafb_dma_irq(int irq, void *data) +{ + int csr; + irqreturn_t ret = IRQ_NONE; + + spin_lock(&global_dev.reg_lock); + csr = viafb_mmio_read(VDMA_CSR0); + if (csr & VDMA_C_DONE) { + viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE); + complete(&viafb_dma_completion); + ret = IRQ_HANDLED; + } + spin_unlock(&global_dev.reg_lock); + return ret; +} + +/* + * Indicate a need for DMA functionality. + */ +int viafb_request_dma(void) +{ + int ret = 0; + + /* + * Only VX855 is supported currently. + */ + if (global_dev.chip_type != UNICHROME_VX855) + return -ENODEV; + /* + * Note the new user and set up our interrupt handler + * if need be. + */ + mutex_lock(&viafb_dma_lock); + viafb_dma_users++; + if (viafb_dma_users == 1) { + ret = request_irq(global_dev.pdev->irq, viafb_dma_irq, + IRQF_SHARED, "via-dma", &viafb_dma_users); + if (ret) + viafb_dma_users--; + else + viafb_irq_enable(VDE_I_DMA0TDEN); + } + mutex_unlock(&viafb_dma_lock); + return ret; +} +EXPORT_SYMBOL_GPL(viafb_request_dma); + +void viafb_release_dma(void) +{ + mutex_lock(&viafb_dma_lock); + viafb_dma_users--; + if (viafb_dma_users == 0) { + viafb_irq_disable(VDE_I_DMA0TDEN); + free_irq(global_dev.pdev->irq, &viafb_dma_users); + } + mutex_unlock(&viafb_dma_lock); +} +EXPORT_SYMBOL_GPL(viafb_release_dma); + + +#if 0 +/* + * Copy a single buffer from FB memory, synchronously. This code works + * but is not currently used. + */ +void viafb_dma_copy_out(unsigned int offset, dma_addr_t paddr, int len) +{ + unsigned long flags; + int csr; + + mutex_lock(&viafb_dma_lock); + init_completion(&viafb_dma_completion); + /* + * Program the controller. + */ + spin_lock_irqsave(&global_dev.reg_lock, flags); + viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_DONE); + /* Enable ints; must happen after CSR0 write! */ + viafb_mmio_write(VDMA_MR0, VDMA_MR_TDIE); + viafb_mmio_write(VDMA_MARL0, (int) (paddr & 0xfffffff0)); + viafb_mmio_write(VDMA_MARH0, (int) ((paddr >> 28) & 0xfff)); + /* Data sheet suggests DAR0 should be <<4, but it lies */ + viafb_mmio_write(VDMA_DAR0, offset); + viafb_mmio_write(VDMA_DQWCR0, len >> 4); + viafb_mmio_write(VDMA_TMR0, 0); + viafb_mmio_write(VDMA_DPRL0, 0); + viafb_mmio_write(VDMA_DPRH0, 0); + viafb_mmio_write(VDMA_PMR0, 0); + csr = viafb_mmio_read(VDMA_CSR0); + viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_START); + spin_unlock_irqrestore(&global_dev.reg_lock, flags); + /* + * Now we just wait until the interrupt handler says + * we're done. + */ + wait_for_completion_interruptible(&viafb_dma_completion); + viafb_mmio_write(VDMA_MR0, 0); /* Reset int enable */ + mutex_unlock(&viafb_dma_lock); +} +EXPORT_SYMBOL_GPL(viafb_dma_copy_out); +#endif + +/* + * Do a scatter/gather DMA copy from FB memory. You must have done + * a successful call to viafb_request_dma() first. + */ +int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg) +{ + struct viafb_vx855_dma_descr *descr; + void *descrpages; + dma_addr_t descr_handle; + unsigned long flags; + int i; + struct scatterlist *sgentry; + dma_addr_t nextdesc; + /* + * Get a place to put the descriptors. + */ + descrpages = dma_alloc_coherent(&global_dev.pdev->dev, + nsg*sizeof(struct viafb_vx855_dma_descr), + &descr_handle, GFP_KERNEL); + if (descrpages == NULL) { + dev_err(&global_dev.pdev->dev, "Unable to get descr page.\n"); + return -ENOMEM; + } + mutex_lock(&viafb_dma_lock); + /* + * Fill them in. + */ + descr = descrpages; + nextdesc = descr_handle + sizeof(struct viafb_vx855_dma_descr); + for_each_sg(sg, sgentry, nsg, i) { + dma_addr_t paddr = sg_dma_address(sgentry); + descr->addr_low = paddr & 0xfffffff0; + descr->addr_high = ((u64) paddr >> 32) & 0x0fff; + descr->fb_offset = offset; + descr->seg_size = sg_dma_len(sgentry) >> 4; + descr->tile_mode = 0; + descr->next_desc_low = (nextdesc&0xfffffff0) | VIAFB_DMA_MAGIC; + descr->next_desc_high = ((u64) nextdesc >> 32) & 0x0fff; + descr->pad = 0xffffffff; /* VIA driver does this */ + offset += sg_dma_len(sgentry); + nextdesc += sizeof(struct viafb_vx855_dma_descr); + descr++; + } + descr[-1].next_desc_low = VIAFB_DMA_FINAL_SEGMENT|VIAFB_DMA_MAGIC; + /* + * Program the engine. + */ + spin_lock_irqsave(&global_dev.reg_lock, flags); + init_completion(&viafb_dma_completion); + viafb_mmio_write(VDMA_DQWCR0, 0); + viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_DONE); + viafb_mmio_write(VDMA_MR0, VDMA_MR_TDIE | VDMA_MR_CHAIN); + viafb_mmio_write(VDMA_DPRL0, descr_handle | VIAFB_DMA_MAGIC); + viafb_mmio_write(VDMA_DPRH0, + (((u64)descr_handle >> 32) & 0x0fff) | 0xf0000); + (void) viafb_mmio_read(VDMA_CSR0); + viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_START); + spin_unlock_irqrestore(&global_dev.reg_lock, flags); + /* + * Now we just wait until the interrupt handler says + * we're done. Except that, actually, we need to wait a little + * longer: the interrupts seem to jump the gun a little and we + * get corrupted frames sometimes. + */ + wait_for_completion_timeout(&viafb_dma_completion, 1); + msleep(1); + if ((viafb_mmio_read(VDMA_CSR0)&VDMA_C_DONE) == 0) + printk(KERN_ERR "VIA DMA timeout!\n"); + /* + * Clean up and we're done. + */ + viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE); + viafb_mmio_write(VDMA_MR0, 0); /* Reset int enable */ + mutex_unlock(&viafb_dma_lock); + dma_free_coherent(&global_dev.pdev->dev, + nsg*sizeof(struct viafb_vx855_dma_descr), descrpages, + descr_handle); + return 0; +} +EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg); + + +/* ---------------------------------------------------------------------- */ /* * Figure out how big our framebuffer memory is. Kind of ugly, * but evidently we can't trust the information found in the diff --git a/drivers/video/via/via-core.h b/drivers/video/via/via-core.h index ba64b36d58e3..3d03141d6074 100644 --- a/drivers/video/via/via-core.h +++ b/drivers/video/via/via-core.h @@ -131,4 +131,33 @@ void viafb_irq_disable(u32 mask); #define VDE_I_LVDSSIEN 0x40000000 /* LVDS Sense enable */ #define VDE_I_ENABLE 0x80000000 /* Global interrupt enable */ +/* + * DMA management. + */ +int viafb_request_dma(void); +void viafb_release_dma(void); +/* void viafb_dma_copy_out(unsigned int offset, dma_addr_t paddr, int len); */ +int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg); + +/* + * DMA Controller registers. + */ +#define VDMA_MR0 0xe00 /* Mod reg 0 */ +#define VDMA_MR_CHAIN 0x01 /* Chaining mode */ +#define VDMA_MR_TDIE 0x02 /* Transfer done int enable */ +#define VDMA_CSR0 0xe04 /* Control/status */ +#define VDMA_C_ENABLE 0x01 /* DMA Enable */ +#define VDMA_C_START 0x02 /* Start a transfer */ +#define VDMA_C_ABORT 0x04 /* Abort a transfer */ +#define VDMA_C_DONE 0x08 /* Transfer is done */ +#define VDMA_MARL0 0xe20 /* Mem addr low */ +#define VDMA_MARH0 0xe24 /* Mem addr high */ +#define VDMA_DAR0 0xe28 /* Device address */ +#define VDMA_DQWCR0 0xe2c /* Count (16-byte) */ +#define VDMA_TMR0 0xe30 /* Tile mode reg */ +#define VDMA_DPRL0 0xe34 /* Not sure */ +#define VDMA_DPR_IN 0x08 /* Inbound transfer to FB */ +#define VDMA_DPRH0 0xe38 +#define VDMA_PMR0 (0xe00 + 0x134) /* Pitch mode */ + #endif /* __VIA_CORE_H__ */ -- cgit v1.2.3 From c2b12cd496bbe5eff6a48bc669fe6b0c56f2b3d9 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 23 Apr 2010 10:31:13 -0600 Subject: viafb: Reserve framebuffer memory for the upcoming camera driver The camera engine captures to framebuffer memory, so we need to set some aside for that purpose. There is no proper memory allocator for fbmem; instead, accel.c just trims some space off the top. Alas, without creating that proper memory allocator, the only way to make this work is to hack it into the same bit of code in accel.c. The allocation must happen *after* the others (some code, including user-space XV stuff, makes assumptions on where the cursor space is), and before the rest of the framebuffer is set up. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/accel.c | 16 ++++++++++++++++ drivers/video/via/via-core.h | 10 ++++++++++ 2 files changed, 26 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index e77746857c8f..189aba41f9b9 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -370,6 +370,22 @@ int viafb_init_engine(struct fb_info *info) viapar->shared->vq_vram_addr = viapar->fbmem_free; viapar->fbmem_used += VQ_SIZE; +#if defined(CONFIG_FB_VIA_CAMERA) || defined(CONFIG_FB_VIA_CAMERA_MODULE) + /* + * Set aside a chunk of framebuffer memory for the camera + * driver. Someday this driver probably needs a proper allocator + * for fbmem; for now, we just have to do this before the + * framebuffer initializes itself. + * + * As for the size: the engine can handle three frames, + * 16 bits deep, up to VGA resolution. + */ + viapar->shared->vdev->camera_fbmem_size = 3*VGA_HEIGHT*VGA_WIDTH*2; + viapar->fbmem_free -= viapar->shared->vdev->camera_fbmem_size; + viapar->fbmem_used += viapar->shared->vdev->camera_fbmem_size; + viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free; +#endif + /* Init AGP and VQ regs */ switch (chip_name) { case UNICHROME_K8M890: diff --git a/drivers/video/via/via-core.h b/drivers/video/via/via-core.h index 3d03141d6074..087c562abaec 100644 --- a/drivers/video/via/via-core.h +++ b/drivers/video/via/via-core.h @@ -78,6 +78,10 @@ struct viafb_dev { unsigned long fbmem_start; long fbmem_len; void __iomem *fbmem; +#if defined(CONFIG_FB_VIA_CAMERA) || defined(CONFIG_FB_VIA_CAMERA_MODULE) + long camera_fbmem_offset; + long camera_fbmem_size; +#endif /* * The MMIO region for device registers. */ @@ -160,4 +164,10 @@ int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg); #define VDMA_DPRH0 0xe38 #define VDMA_PMR0 (0xe00 + 0x134) /* Pitch mode */ +/* + * Useful stuff that probably belongs somewhere global. + */ +#define VGA_WIDTH 640 +#define VGA_HEIGHT 480 + #endif /* __VIA_CORE_H__ */ -- cgit v1.2.3 From 2749413db17723cf894036c0eaf339f289bcc841 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sat, 17 Apr 2010 19:44:52 +0000 Subject: viafb: unify modesetting functions viafb: unify modesetting functions This patch unifies some cleaned up modesetting functions to prepare for moving them to an extra file. This includes make them use via_io and changing there names to reflect that they do not depend on anything framebuffer specific. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/hw.c | 66 ++++++++++++++++++++++---------------------- drivers/video/via/hw.h | 8 +++--- drivers/video/via/viafbdev.c | 17 ++++++------ 3 files changed, 46 insertions(+), 45 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 805151f48ea9..1628a5f93dc2 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -624,50 +624,50 @@ void viafb_set_iga_path(void) } } -void viafb_set_primary_address(u32 addr) +void via_set_primary_address(u32 addr) { - DEBUG_MSG(KERN_DEBUG "viafb_set_primary_address(0x%08X)\n", addr); - viafb_write_reg(CR0D, VIACR, addr & 0xFF); - viafb_write_reg(CR0C, VIACR, (addr >> 8) & 0xFF); - viafb_write_reg(CR34, VIACR, (addr >> 16) & 0xFF); - viafb_write_reg_mask(CR48, VIACR, (addr >> 24) & 0x1F, 0x1F); + DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr); + via_write_reg(VIACR, 0x0D, addr & 0xFF); + via_write_reg(VIACR, 0x0C, (addr >> 8) & 0xFF); + via_write_reg(VIACR, 0x34, (addr >> 16) & 0xFF); + via_write_reg_mask(VIACR, 0x48, (addr >> 24) & 0x1F, 0x1F); } -void viafb_set_secondary_address(u32 addr) +void via_set_secondary_address(u32 addr) { - DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_address(0x%08X)\n", addr); + DEBUG_MSG(KERN_DEBUG "via_set_secondary_address(0x%08X)\n", addr); /* secondary display supports only quadword aligned memory */ - viafb_write_reg_mask(CR62, VIACR, (addr >> 2) & 0xFE, 0xFE); - viafb_write_reg(CR63, VIACR, (addr >> 10) & 0xFF); - viafb_write_reg(CR64, VIACR, (addr >> 18) & 0xFF); - viafb_write_reg_mask(CRA3, VIACR, (addr >> 26) & 0x07, 0x07); + via_write_reg_mask(VIACR, 0x62, (addr >> 2) & 0xFE, 0xFE); + via_write_reg(VIACR, 0x63, (addr >> 10) & 0xFF); + via_write_reg(VIACR, 0x64, (addr >> 18) & 0xFF); + via_write_reg_mask(VIACR, 0xA3, (addr >> 26) & 0x07, 0x07); } -void viafb_set_primary_pitch(u32 pitch) +void via_set_primary_pitch(u32 pitch) { - DEBUG_MSG(KERN_DEBUG "viafb_set_primary_pitch(0x%08X)\n", pitch); + DEBUG_MSG(KERN_DEBUG "via_set_primary_pitch(0x%08X)\n", pitch); /* spec does not say that first adapter skips 3 bits but old * code did it and seems to be reasonable in analogy to 2nd adapter */ pitch = pitch >> 3; - viafb_write_reg(0x13, VIACR, pitch & 0xFF); - viafb_write_reg_mask(0x35, VIACR, (pitch >> (8 - 5)) & 0xE0, 0xE0); + via_write_reg(VIACR, 0x13, pitch & 0xFF); + via_write_reg_mask(VIACR, 0x35, (pitch >> (8 - 5)) & 0xE0, 0xE0); } -void viafb_set_secondary_pitch(u32 pitch) +void via_set_secondary_pitch(u32 pitch) { - DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_pitch(0x%08X)\n", pitch); + DEBUG_MSG(KERN_DEBUG "via_set_secondary_pitch(0x%08X)\n", pitch); pitch = pitch >> 3; - viafb_write_reg(0x66, VIACR, pitch & 0xFF); - viafb_write_reg_mask(0x67, VIACR, (pitch >> 8) & 0x03, 0x03); - viafb_write_reg_mask(0x71, VIACR, (pitch >> (10 - 7)) & 0x80, 0x80); + via_write_reg(VIACR, 0x66, pitch & 0xFF); + via_write_reg_mask(VIACR, 0x67, (pitch >> 8) & 0x03, 0x03); + via_write_reg_mask(VIACR, 0x71, (pitch >> (10 - 7)) & 0x80, 0x80); } -void viafb_set_primary_color_depth(u8 depth) +void via_set_primary_color_depth(u8 depth) { u8 value; - DEBUG_MSG(KERN_DEBUG "viafb_set_primary_color_depth(%d)\n", depth); + DEBUG_MSG(KERN_DEBUG "via_set_primary_color_depth(%d)\n", depth); switch (depth) { case 8: value = 0x00; @@ -685,19 +685,19 @@ void viafb_set_primary_color_depth(u8 depth) value = 0x08; break; default: - printk(KERN_WARNING "viafb_set_primary_color_depth: " + printk(KERN_WARNING "via_set_primary_color_depth: " "Unsupported depth: %d\n", depth); return; } - viafb_write_reg_mask(0x15, VIASR, value, 0x1C); + via_write_reg_mask(VIASR, 0x15, value, 0x1C); } -void viafb_set_secondary_color_depth(u8 depth) +void via_set_secondary_color_depth(u8 depth) { u8 value; - DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_color_depth(%d)\n", depth); + DEBUG_MSG(KERN_DEBUG "via_set_secondary_color_depth(%d)\n", depth); switch (depth) { case 8: value = 0x00; @@ -712,12 +712,12 @@ void viafb_set_secondary_color_depth(u8 depth) value = 0x80; break; default: - printk(KERN_WARNING "viafb_set_secondary_color_depth: " + printk(KERN_WARNING "via_set_secondary_color_depth: " "Unsupported depth: %d\n", depth); return; } - viafb_write_reg_mask(0x67, VIACR, value, 0xC0); + via_write_reg_mask(VIACR, 0x67, value, 0xC0); } static void set_color_register(u8 index, u8 red, u8 green, u8 blue) @@ -2268,11 +2268,11 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, } } - viafb_set_primary_pitch(viafbinfo->fix.line_length); - viafb_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length + via_set_primary_pitch(viafbinfo->fix.line_length); + via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length : viafbinfo->fix.line_length); - viafb_set_primary_color_depth(viaparinfo->depth); - viafb_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth + via_set_primary_color_depth(viaparinfo->depth); + via_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth : viaparinfo->depth); /* Update Refresh Rate Setting */ diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index 23c319010913..641a5fa4bd33 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -910,10 +910,10 @@ void viafb_update_device_setting(int hres, int vres, int bpp, int vmode_refresh, int flag); void viafb_set_iga_path(void); -void viafb_set_primary_address(u32 addr); -void viafb_set_secondary_address(u32 addr); -void viafb_set_primary_pitch(u32 pitch); -void viafb_set_secondary_pitch(u32 pitch); +void via_set_primary_address(u32 addr); +void via_set_secondary_address(u32 addr); +void via_set_primary_pitch(u32 pitch); +void via_set_secondary_pitch(u32 pitch); void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue); void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 70ed71facd87..e94f913f87be 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -317,12 +317,12 @@ static int viafb_pan_display(struct fb_var_screeninfo *var, DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); if (!viafb_dual_fb) { - viafb_set_primary_address(vram_addr); - viafb_set_secondary_address(vram_addr); + via_set_primary_address(vram_addr); + via_set_secondary_address(vram_addr); } else if (viapar->iga_path == IGA1) - viafb_set_primary_address(vram_addr); + via_set_primary_address(vram_addr); else - viafb_set_secondary_address(vram_addr); + via_set_secondary_address(vram_addr); return 0; } @@ -1018,8 +1018,8 @@ static void viafb_set_device(struct device_t active_dev) viafb_SAMM_ON = active_dev.samm; viafb_primary_dev = active_dev.primary_dev; - viafb_set_primary_address(0); - viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0); + via_set_primary_address(0); + via_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0); viafb_set_iga_path(); } @@ -1165,8 +1165,9 @@ static int apply_device_setting(struct viafb_ioctl_setting setting_info, if (viafb_SAMM_ON) viafb_primary_dev = setting_info.primary_device; - viafb_set_primary_address(0); - viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0); + via_set_primary_address(0); + via_set_secondary_address(viafb_SAMM_ON ? + viafb_second_offset : 0); viafb_set_iga_path(); } need_set_mode = 1; -- cgit v1.2.3 From 100e74a150d3a31d4c12658c926429ceb880d2f7 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sat, 17 Apr 2010 19:44:53 +0000 Subject: viafb: move some modesetting functions to a seperate file viafb: move some modesetting functions to a seperate file This patch moves the modesetting functions which are already cleaned up to a seperate file. Just the beginning to bring some structure in this mess. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/Makefile | 3 +- drivers/video/via/hw.c | 96 --------------------------- drivers/video/via/hw.h | 5 +- drivers/video/via/via_modesetting.c | 126 ++++++++++++++++++++++++++++++++++++ drivers/video/via/via_modesetting.h | 38 +++++++++++ 5 files changed, 166 insertions(+), 102 deletions(-) create mode 100644 drivers/video/via/via_modesetting.c create mode 100644 drivers/video/via/via_modesetting.h (limited to 'drivers/video') diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile index 8c42a42c3dbb..d496adb0f832 100644 --- a/drivers/video/via/Makefile +++ b/drivers/video/via/Makefile @@ -6,5 +6,4 @@ obj-$(CONFIG_FB_VIA) += viafb.o viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \ via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o \ - via-core.o via-gpio.o - + via-core.o via-gpio.o via_modesetting.o diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 1628a5f93dc2..d474fbee3350 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -624,102 +624,6 @@ void viafb_set_iga_path(void) } } -void via_set_primary_address(u32 addr) -{ - DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr); - via_write_reg(VIACR, 0x0D, addr & 0xFF); - via_write_reg(VIACR, 0x0C, (addr >> 8) & 0xFF); - via_write_reg(VIACR, 0x34, (addr >> 16) & 0xFF); - via_write_reg_mask(VIACR, 0x48, (addr >> 24) & 0x1F, 0x1F); -} - -void via_set_secondary_address(u32 addr) -{ - DEBUG_MSG(KERN_DEBUG "via_set_secondary_address(0x%08X)\n", addr); - /* secondary display supports only quadword aligned memory */ - via_write_reg_mask(VIACR, 0x62, (addr >> 2) & 0xFE, 0xFE); - via_write_reg(VIACR, 0x63, (addr >> 10) & 0xFF); - via_write_reg(VIACR, 0x64, (addr >> 18) & 0xFF); - via_write_reg_mask(VIACR, 0xA3, (addr >> 26) & 0x07, 0x07); -} - -void via_set_primary_pitch(u32 pitch) -{ - DEBUG_MSG(KERN_DEBUG "via_set_primary_pitch(0x%08X)\n", pitch); - /* spec does not say that first adapter skips 3 bits but old - * code did it and seems to be reasonable in analogy to 2nd adapter - */ - pitch = pitch >> 3; - via_write_reg(VIACR, 0x13, pitch & 0xFF); - via_write_reg_mask(VIACR, 0x35, (pitch >> (8 - 5)) & 0xE0, 0xE0); -} - -void via_set_secondary_pitch(u32 pitch) -{ - DEBUG_MSG(KERN_DEBUG "via_set_secondary_pitch(0x%08X)\n", pitch); - pitch = pitch >> 3; - via_write_reg(VIACR, 0x66, pitch & 0xFF); - via_write_reg_mask(VIACR, 0x67, (pitch >> 8) & 0x03, 0x03); - via_write_reg_mask(VIACR, 0x71, (pitch >> (10 - 7)) & 0x80, 0x80); -} - -void via_set_primary_color_depth(u8 depth) -{ - u8 value; - - DEBUG_MSG(KERN_DEBUG "via_set_primary_color_depth(%d)\n", depth); - switch (depth) { - case 8: - value = 0x00; - break; - case 15: - value = 0x04; - break; - case 16: - value = 0x14; - break; - case 24: - value = 0x0C; - break; - case 30: - value = 0x08; - break; - default: - printk(KERN_WARNING "via_set_primary_color_depth: " - "Unsupported depth: %d\n", depth); - return; - } - - via_write_reg_mask(VIASR, 0x15, value, 0x1C); -} - -void via_set_secondary_color_depth(u8 depth) -{ - u8 value; - - DEBUG_MSG(KERN_DEBUG "via_set_secondary_color_depth(%d)\n", depth); - switch (depth) { - case 8: - value = 0x00; - break; - case 16: - value = 0x40; - break; - case 24: - value = 0xC0; - break; - case 30: - value = 0x80; - break; - default: - printk(KERN_WARNING "via_set_secondary_color_depth: " - "Unsupported depth: %d\n", depth); - return; - } - - via_write_reg_mask(VIACR, 0x67, value, 0xC0); -} - static void set_color_register(u8 index, u8 red, u8 green, u8 blue) { outb(0xFF, 0x3C6); /* bit mask of palette */ diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index 641a5fa4bd33..a58701f3bf7f 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -25,6 +25,7 @@ #include "viamode.h" #include "global.h" #include "via_io.h" +#include "via_modesetting.h" #define viafb_read_reg(p, i) via_read_reg(p, i) #define viafb_write_reg(i, p, d) via_write_reg(p, i, d) @@ -910,10 +911,6 @@ void viafb_update_device_setting(int hres, int vres, int bpp, int vmode_refresh, int flag); void viafb_set_iga_path(void); -void via_set_primary_address(u32 addr); -void via_set_secondary_address(u32 addr); -void via_set_primary_pitch(u32 pitch); -void via_set_secondary_pitch(u32 pitch); void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue); void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c new file mode 100644 index 000000000000..69ff28575008 --- /dev/null +++ b/drivers/video/via/via_modesetting.c @@ -0,0 +1,126 @@ +/* + * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. + * Copyright 2010 Florian Tobias Schandinat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; + * either version 2, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE.See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +/* + * basic modesetting functions + */ + +#include +#include "via_modesetting.h" +#include "via_io.h" +#include "share.h" +#include "debug.h" + +void via_set_primary_address(u32 addr) +{ + DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr); + via_write_reg(VIACR, 0x0D, addr & 0xFF); + via_write_reg(VIACR, 0x0C, (addr >> 8) & 0xFF); + via_write_reg(VIACR, 0x34, (addr >> 16) & 0xFF); + via_write_reg_mask(VIACR, 0x48, (addr >> 24) & 0x1F, 0x1F); +} + +void via_set_secondary_address(u32 addr) +{ + DEBUG_MSG(KERN_DEBUG "via_set_secondary_address(0x%08X)\n", addr); + /* secondary display supports only quadword aligned memory */ + via_write_reg_mask(VIACR, 0x62, (addr >> 2) & 0xFE, 0xFE); + via_write_reg(VIACR, 0x63, (addr >> 10) & 0xFF); + via_write_reg(VIACR, 0x64, (addr >> 18) & 0xFF); + via_write_reg_mask(VIACR, 0xA3, (addr >> 26) & 0x07, 0x07); +} + +void via_set_primary_pitch(u32 pitch) +{ + DEBUG_MSG(KERN_DEBUG "via_set_primary_pitch(0x%08X)\n", pitch); + /* spec does not say that first adapter skips 3 bits but old + * code did it and seems to be reasonable in analogy to 2nd adapter + */ + pitch = pitch >> 3; + via_write_reg(VIACR, 0x13, pitch & 0xFF); + via_write_reg_mask(VIACR, 0x35, (pitch >> (8 - 5)) & 0xE0, 0xE0); +} + +void via_set_secondary_pitch(u32 pitch) +{ + DEBUG_MSG(KERN_DEBUG "via_set_secondary_pitch(0x%08X)\n", pitch); + pitch = pitch >> 3; + via_write_reg(VIACR, 0x66, pitch & 0xFF); + via_write_reg_mask(VIACR, 0x67, (pitch >> 8) & 0x03, 0x03); + via_write_reg_mask(VIACR, 0x71, (pitch >> (10 - 7)) & 0x80, 0x80); +} + +void via_set_primary_color_depth(u8 depth) +{ + u8 value; + + DEBUG_MSG(KERN_DEBUG "via_set_primary_color_depth(%d)\n", depth); + switch (depth) { + case 8: + value = 0x00; + break; + case 15: + value = 0x04; + break; + case 16: + value = 0x14; + break; + case 24: + value = 0x0C; + break; + case 30: + value = 0x08; + break; + default: + printk(KERN_WARNING "via_set_primary_color_depth: " + "Unsupported depth: %d\n", depth); + return; + } + + via_write_reg_mask(VIASR, 0x15, value, 0x1C); +} + +void via_set_secondary_color_depth(u8 depth) +{ + u8 value; + + DEBUG_MSG(KERN_DEBUG "via_set_secondary_color_depth(%d)\n", depth); + switch (depth) { + case 8: + value = 0x00; + break; + case 16: + value = 0x40; + break; + case 24: + value = 0xC0; + break; + case 30: + value = 0x80; + break; + default: + printk(KERN_WARNING "via_set_secondary_color_depth: " + "Unsupported depth: %d\n", depth); + return; + } + + via_write_reg_mask(VIACR, 0x67, value, 0xC0); +} diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h new file mode 100644 index 000000000000..ae35cfdeb37c --- /dev/null +++ b/drivers/video/via/via_modesetting.h @@ -0,0 +1,38 @@ +/* + * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. + * Copyright 2010 Florian Tobias Schandinat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; + * either version 2, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE.See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +/* + * basic modesetting functions + */ + +#ifndef __VIA_MODESETTING_H__ +#define __VIA_MODESETTING_H__ + +#include + +void via_set_primary_address(u32 addr); +void via_set_secondary_address(u32 addr); +void via_set_primary_pitch(u32 pitch); +void via_set_secondary_pitch(u32 pitch); +void via_set_primary_color_depth(u8 depth); +void via_set_secondary_color_depth(u8 depth); + +#endif /* __VIA_MODESETTING_H__ */ -- cgit v1.2.3 From 384c3041aeaf77d299b0d4a62481850fed86e53b Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sat, 17 Apr 2010 19:44:54 +0000 Subject: viafb: replace inb/outb viafb: replace inb/outb This patch replaces occurences of inb/outb with via_write_reg and via_write_reg_mask where this is possible to improve code readability. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/hw.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index d474fbee3350..b2bb24e23f33 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -1008,16 +1008,12 @@ void viafb_load_reg(int timing_value, int viafb_load_reg_num, void viafb_write_regx(struct io_reg RegTable[], int ItemNum) { int i; - unsigned char RegTemp; /*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */ - for (i = 0; i < ItemNum; i++) { - outb(RegTable[i].index, RegTable[i].port); - RegTemp = inb(RegTable[i].port + 1); - RegTemp = (RegTemp & (~RegTable[i].mask)) | RegTable[i].value; - outb(RegTemp, RegTable[i].port + 1); - } + for (i = 0; i < ItemNum; i++) + via_write_reg_mask(RegTable[i].port, RegTable[i].index, + RegTable[i].value, RegTable[i].mask); } void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga) @@ -2130,10 +2126,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, outb(VPIT.Misc, VIAWMisc); /* Write Sequencer */ - for (i = 1; i <= StdSR; i++) { - outb(i, VIASR); - outb(VPIT.SR[i - 1], VIASR + 1); - } + for (i = 1; i <= StdSR; i++) + via_write_reg(VIASR, i, VPIT.SR[i - 1]); viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2); viafb_set_iga_path(); @@ -2142,10 +2136,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, viafb_fill_crtc_timing(crt_timing, vmode_tbl, video_bpp / 8, IGA1); /* Write Graphic Controller */ - for (i = 0; i < StdGR; i++) { - outb(i, VIAGR); - outb(VPIT.GR[i], VIAGR + 1); - } + for (i = 0; i < StdGR; i++) + via_write_reg(VIAGR, i, VPIT.GR[i]); /* Write Attribute Controller */ for (i = 0; i < StdAR; i++) { -- cgit v1.2.3 From 162fc8c0c03d5b8536f14cbd2cdfb399c50c05ec Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sat, 17 Apr 2010 19:44:55 +0000 Subject: viafb: improve misc register handling viafb: improve misc register handling This patch improves the misc register handling by adding a modify function for this to via_io.h and moving expanded definitions of the relevant ports there. The code was changed to use those to improve readability. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/hw.c | 27 ++++++++------------------- drivers/video/via/share.h | 2 -- drivers/video/via/via_io.h | 9 +++++++++ 3 files changed, 17 insertions(+), 21 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index b2bb24e23f33..e356fe8d8a90 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -1394,8 +1394,6 @@ u32 viafb_get_clk_value(int clk) /* Set VCLK*/ void viafb_set_vclock(u32 CLK, int set_iga) { - unsigned char RegTemp; - /* H.W. Reset : ON */ viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); @@ -1468,8 +1466,7 @@ void viafb_set_vclock(u32 CLK, int set_iga) } /* Fire! */ - RegTemp = inb(VIARMisc); - outb(RegTemp | (BIT2 + BIT3), VIAWMisc); + via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ } void viafb_load_crtc_timing(struct display_timing device_timing, @@ -1713,6 +1710,7 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, int index = 0; int h_addr, v_addr; u32 pll_D_N; + u8 polarity = 0; for (i = 0; i < video_mode->mode_array; i++) { index = i; @@ -1741,20 +1739,11 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, v_addr = crt_reg.ver_addr; /* update polarity for CRT timing */ - if (crt_table[index].h_sync_polarity == NEGATIVE) { - if (crt_table[index].v_sync_polarity == NEGATIVE) - outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | - (BIT6 + BIT7), VIAWMisc); - else - outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT6), - VIAWMisc); - } else { - if (crt_table[index].v_sync_polarity == NEGATIVE) - outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT7), - VIAWMisc); - else - outb((inb(VIARMisc) & (~(BIT6 + BIT7))), VIAWMisc); - } + if (crt_table[index].h_sync_polarity == NEGATIVE) + polarity |= BIT6; + if (crt_table[index].v_sync_polarity == NEGATIVE) + polarity |= BIT7; + via_write_misc_reg_mask(polarity, BIT6 | BIT7); if (set_iga == IGA1) { viafb_unlock_crt(); @@ -2123,7 +2112,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, /* Fill VPIT Parameters */ /* Write Misc Register */ - outb(VPIT.Misc, VIAWMisc); + outb(VPIT.Misc, VIA_MISC_REG_WRITE); /* Write Sequencer */ for (i = 1; i <= StdSR; i++) diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index f974c7333522..861b4142efad 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h @@ -45,8 +45,6 @@ /* standard VGA IO port */ -#define VIARMisc 0x3CC -#define VIAWMisc 0x3C2 #define VIAStatus 0x3DA #define VIACR 0x3D4 #define VIASR 0x3C4 diff --git a/drivers/video/via/via_io.h b/drivers/video/via/via_io.h index e1c1093def00..a3d2aca65540 100644 --- a/drivers/video/via/via_io.h +++ b/drivers/video/via/via_io.h @@ -29,6 +29,9 @@ #include #include +#define VIA_MISC_REG_READ 0x03CC +#define VIA_MISC_REG_WRITE 0x03C2 + /* * Indexed port operations. Note that these are all multi-op * functions; every invocation will be racy if you're not holding @@ -55,4 +58,10 @@ static inline void via_write_reg_mask(u16 port, u8 index, u8 data, u8 mask) outb((data & mask) | (old & ~mask), port + 1); } +static inline void via_write_misc_reg_mask(u8 data, u8 mask) +{ + u8 old = inb(VIA_MISC_REG_READ); + outb((data & mask) | (old & ~mask), VIA_MISC_REG_WRITE); +} + #endif /* __VIA_IO_H__ */ -- cgit v1.2.3 From 2fed547c0298e1465d62b34a75a7b76353fee7d3 Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sat, 17 Apr 2010 19:44:56 +0000 Subject: viafb: fix proc entry removal viafb: fix proc entry removal Trying to remove unregistered proc entries became painful and is useless anyway. So remove the removal of an entry that was never registered and duplicate the logic for one which is added conditionally. Additionally move the removal above releasing fb_info as we still need the information. This prevents tainting the kernel by the procfs warn on and avoiding access to already freed memory is probably also a good idea. Signed-off-by: Florian Tobias Schandinat --- drivers/video/via/viafbdev.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index e94f913f87be..51e9106138ce 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -1702,13 +1702,16 @@ static void viafb_init_proc(struct proc_dir_entry **viafb_entry) } static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) { - /* no problem if it was not registered */ + struct chip_information *chip_info = &viaparinfo->shared->chip_info; + remove_proc_entry("dvp0", viafb_entry);/* parent dir */ remove_proc_entry("dvp1", viafb_entry); remove_proc_entry("dfph", viafb_entry); remove_proc_entry("dfpl", viafb_entry); - remove_proc_entry("vt1636", viafb_entry); - remove_proc_entry("vt1625", viafb_entry); + if (chip_info->lvds_chip_info.lvds_chip_name == VT1636_LVDS + || chip_info->lvds_chip_info2.lvds_chip_name == VT1636_LVDS) + remove_proc_entry("vt1636", viafb_entry); + remove_proc_entry("viafb", NULL); } @@ -1967,12 +1970,10 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev) unregister_framebuffer(viafbinfo); if (viafb_dual_fb) unregister_framebuffer(viafbinfo1); - + viafb_remove_proc(viaparinfo->shared->proc_entry); framebuffer_release(viafbinfo); if (viafb_dual_fb) framebuffer_release(viafbinfo1); - - viafb_remove_proc(viaparinfo->shared->proc_entry); } #ifndef MODULE -- cgit v1.2.3 From 2b78a963c800252a0016785813cc5140c006145c Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sat, 17 Apr 2010 19:44:57 +0000 Subject: viafb: make procfs entries optional viafb: make procfs entries optional This patch adds a config option to enable procfs entries for direct hardware access. This was the old behaviour but the option defaults to no as this is really ugly and should not be needed if the driver works correct (and if it doesn't, it needs to be fixed). That stuff is really something that should - not be needed at all (the driver should be capable of doing it) - not be there (debugfs would be better for such things) So add this option just for backwards compatiblity. Signed-off-by: Florian Tobias Schandinat --- drivers/video/Kconfig | 14 ++++++++++++++ drivers/video/via/viafbdev.c | 8 ++++++++ 2 files changed, 22 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 22c1662de964..fd55c279915c 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1522,6 +1522,20 @@ config FB_VIA To compile this driver as a module, choose M here: the module will be called viafb. +if FB_VIA + +config FB_VIA_DIRECT_PROCFS + bool "direct hardware access via procfs (DEPRECATED)(DANGEROUS)" + depends on FB_VIA + default n + help + Allow direct hardware access to some output registers via procfs. + This is dangerous but may provide the only chance to get the + correct output device configuration. + Its use is strongly discouraged. + +endif + config FB_NEOMAGIC tristate "NeoMagic display support" depends on FB && PCI diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 51e9106138ce..3d033186a822 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -1326,6 +1326,8 @@ static void parse_dvi_port(void) output_interface); } +#ifdef CONFIG_FB_VIA_DIRECT_PROCFS + /* * The proc filesystem read/write function, a simple proc implement to * get/set the value of DPA DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1, @@ -1715,6 +1717,8 @@ static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) remove_proc_entry("viafb", NULL); } +#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */ + static int parse_mode(const char *str, u32 *xres, u32 *yres) { char *ptr; @@ -1943,7 +1947,9 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) viafbinfo->node, viafbinfo->fix.id, default_var.xres, default_var.yres, default_var.bits_per_pixel); +#ifdef CONFIG_FB_VIA_DIRECT_PROCFS viafb_init_proc(&viaparinfo->shared->proc_entry); +#endif viafb_init_dac(IGA2); return 0; @@ -1970,7 +1976,9 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev) unregister_framebuffer(viafbinfo); if (viafb_dual_fb) unregister_framebuffer(viafbinfo1); +#ifdef CONFIG_FB_VIA_DIRECT_PROCFS viafb_remove_proc(viaparinfo->shared->proc_entry); +#endif framebuffer_release(viafbinfo); if (viafb_dual_fb) framebuffer_release(viafbinfo1); -- cgit v1.2.3 From 27fe971d08b43f649358745a55f3c48ac6f413f8 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 30 Apr 2010 09:45:51 -0600 Subject: viafb: Do not remove gpiochip under spinlock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gpiochip_remove() is not meant to be called with interrupts disabled, and there is no need for the lock here in any case. Reported-by: Bruno Prémont Signed-off-by: Jonathan Corbet --- drivers/video/via/via-gpio.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c index 44537be1f070..63cb7acc0faf 100644 --- a/drivers/video/via/via-gpio.c +++ b/drivers/video/via/via-gpio.c @@ -246,7 +246,6 @@ static int viafb_gpio_remove(struct platform_device *platdev) unsigned long flags; int ret = 0, i; - spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags); /* * Get unregistered. */ @@ -254,16 +253,16 @@ static int viafb_gpio_remove(struct platform_device *platdev) ret = gpiochip_remove(&gpio_config.gpio_chip); if (ret) { /* Somebody still using it? */ printk(KERN_ERR "Viafb: GPIO remove failed\n"); - goto out; + return ret; } } /* * Disable the ports. */ + spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags); for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2) viafb_gpio_disable(gpio_config.active_gpios[i]); gpio_config.gpio_chip.ngpio = 0; -out: spin_unlock_irqrestore(&gpio_config.vdev->reg_lock, flags); return ret; } -- cgit v1.2.3 From 8bbf50fe9c0fb8d83b993ae6d88a4ce27d81b999 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 30 Apr 2010 10:03:57 -0600 Subject: viafb: Fix initialization error paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Properly localize error cleanup, and make sure that the iomem regions are unmapped if framebuffer initialization fails. Reported-by: Bruno Prémont Signed-off-by: Jonathan Corbet --- drivers/video/via/via-core.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index 9929bb1549b6..188c0022dcb4 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c @@ -453,26 +453,40 @@ static int viafb_get_fb_size_from_pci(int chip_type) */ static int __devinit via_pci_setup_mmio(struct viafb_dev *vdev) { + int ret; /* - * Hook up to the device registers. + * Hook up to the device registers. Note that we soldier + * on if it fails; the framebuffer can operate (without + * acceleration) without this region. */ vdev->engine_start = pci_resource_start(vdev->pdev, 1); vdev->engine_len = pci_resource_len(vdev->pdev, 1); - /* If this fails, others will notice later */ vdev->engine_mmio = ioremap_nocache(vdev->engine_start, vdev->engine_len); - + if (vdev->engine_mmio == NULL) + dev_err(&vdev->pdev->dev, + "Unable to map engine MMIO; operation will be " + "slow and crippled.\n"); /* - * Likewise with I/O memory. + * Map in framebuffer memory. For now, failure here is + * fatal. Unfortunately, in the absence of significant + * vmalloc space, failure here is also entirely plausible. + * Eventually we want to move away from mapping this + * entire region. */ vdev->fbmem_start = pci_resource_start(vdev->pdev, 0); - vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type); - if (vdev->fbmem_len < 0) - return vdev->fbmem_len; + ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type); + if (ret < 0) + goto out_unmap; vdev->fbmem = ioremap_nocache(vdev->fbmem_start, vdev->fbmem_len); - if (vdev->fbmem == NULL) - return -ENOMEM; + if (vdev->fbmem == NULL) { + ret = -ENOMEM; + goto out_unmap; + } return 0; +out_unmap: + iounmap(vdev->engine_mmio); + return ret; } static void __devexit via_pci_teardown_mmio(struct viafb_dev *vdev) @@ -572,12 +586,11 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, viafb_int_init(); via_setup_subdevs(&global_dev); /* - * Set up the framebuffer. + * Set up the framebuffer device */ ret = via_fb_pci_probe(&global_dev); if (ret) goto out_subdevs; - return 0; out_subdevs: -- cgit v1.2.3 From 64a6bd6a570c53f1955eaedf3952dcbe9b62da1d Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Wed, 5 May 2010 13:42:49 -0600 Subject: viafb: fold via_io.h into via-core.h Preparatory move toward the ultimate goal of moving pan-subdevice stuff into include/linux. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/hw.h | 1 - drivers/video/via/share.h | 11 ++---- drivers/video/via/via-core.h | 48 +++++++++++++++++++++++++- drivers/video/via/via_io.h | 67 ------------------------------------- drivers/video/via/via_modesetting.c | 2 +- drivers/video/via/via_utility.c | 1 + drivers/video/via/viamode.c | 1 + 7 files changed, 53 insertions(+), 78 deletions(-) delete mode 100644 drivers/video/via/via_io.h (limited to 'drivers/video') diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index a58701f3bf7f..a109de379816 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h @@ -24,7 +24,6 @@ #include "viamode.h" #include "global.h" -#include "via_io.h" #include "via_modesetting.h" #define viafb_read_reg(p, i) via_read_reg(p, i) diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index 861b4142efad..7f0de7f006ad 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h @@ -43,14 +43,9 @@ /* Video Memory Size */ #define VIDEO_MEMORY_SIZE_16M 0x1000000 -/* standard VGA IO port -*/ -#define VIAStatus 0x3DA -#define VIACR 0x3D4 -#define VIASR 0x3C4 -#define VIAGR 0x3CE -#define VIAAR 0x3C0 - +/* + * Lengths of the VPIT structure arrays. + */ #define StdCR 0x19 #define StdSR 0x04 #define StdGR 0x09 diff --git a/drivers/video/via/via-core.h b/drivers/video/via/via-core.h index 087c562abaec..7ffb521e1a7a 100644 --- a/drivers/video/via/via-core.h +++ b/drivers/video/via/via-core.h @@ -1,7 +1,8 @@ /* * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. - * Copyright 2009 Jonathan Corbet + * Copyright 2009-2010 Jonathan Corbet + * Copyright 2010 Florian Tobias Schandinat * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public @@ -22,6 +23,8 @@ #ifndef __VIA_CORE_H__ #define __VIA_CORE_H__ +#include +#include #include #include @@ -170,4 +173,47 @@ int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg); #define VGA_WIDTH 640 #define VGA_HEIGHT 480 +/* + * Indexed port operations. Note that these are all multi-op + * functions; every invocation will be racy if you're not holding + * reg_lock. + */ + +#define VIAStatus 0x3DA /* Non-indexed port */ +#define VIACR 0x3D4 +#define VIASR 0x3C4 +#define VIAGR 0x3CE +#define VIAAR 0x3C0 + +static inline u8 via_read_reg(u16 port, u8 index) +{ + outb(index, port); + return inb(port + 1); +} + +static inline void via_write_reg(u16 port, u8 index, u8 data) +{ + outb(index, port); + outb(data, port + 1); +} + +static inline void via_write_reg_mask(u16 port, u8 index, u8 data, u8 mask) +{ + u8 old; + + outb(index, port); + old = inb(port + 1); + outb((data & mask) | (old & ~mask), port + 1); +} + +#define VIA_MISC_REG_READ 0x03CC +#define VIA_MISC_REG_WRITE 0x03C2 + +static inline void via_write_misc_reg_mask(u8 data, u8 mask) +{ + u8 old = inb(VIA_MISC_REG_READ); + outb((data & mask) | (old & ~mask), VIA_MISC_REG_WRITE); +} + + #endif /* __VIA_CORE_H__ */ diff --git a/drivers/video/via/via_io.h b/drivers/video/via/via_io.h deleted file mode 100644 index a3d2aca65540..000000000000 --- a/drivers/video/via/via_io.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. - * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. - * Copyright 2010 Florian Tobias Schandinat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; - * either version 2, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE.See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -/* - * basic io functions - */ - -#ifndef __VIA_IO_H__ -#define __VIA_IO_H__ - -#include -#include - -#define VIA_MISC_REG_READ 0x03CC -#define VIA_MISC_REG_WRITE 0x03C2 - -/* - * Indexed port operations. Note that these are all multi-op - * functions; every invocation will be racy if you're not holding - * reg_lock. - */ -static inline u8 via_read_reg(u16 port, u8 index) -{ - outb(index, port); - return inb(port + 1); -} - -static inline void via_write_reg(u16 port, u8 index, u8 data) -{ - outb(index, port); - outb(data, port + 1); -} - -static inline void via_write_reg_mask(u16 port, u8 index, u8 data, u8 mask) -{ - u8 old; - - outb(index, port); - old = inb(port + 1); - outb((data & mask) | (old & ~mask), port + 1); -} - -static inline void via_write_misc_reg_mask(u8 data, u8 mask) -{ - u8 old = inb(VIA_MISC_REG_READ); - outb((data & mask) | (old & ~mask), VIA_MISC_REG_WRITE); -} - -#endif /* __VIA_IO_H__ */ diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c index 69ff28575008..b4e735cc350e 100644 --- a/drivers/video/via/via_modesetting.c +++ b/drivers/video/via/via_modesetting.c @@ -25,7 +25,7 @@ #include #include "via_modesetting.h" -#include "via_io.h" +#include "via-core.h" #include "share.h" #include "debug.h" diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c index aefdeeec89b1..575703141868 100644 --- a/drivers/video/via/via_utility.c +++ b/drivers/video/via/via_utility.c @@ -19,6 +19,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "via-core.h" #include "global.h" void viafb_get_device_support_state(u32 *support_state) diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index 6f3bcda8cb47..2fdb9e6724a4 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c @@ -19,6 +19,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "via-core.h" #include "global.h" struct res_map_refresh res_map_refresh_tbl[] = { /*hres, vres, vclock, vmode_refresh*/ -- cgit v1.2.3 From 4a28ea9cedaa673b8a1a7f84628d784d020f3b47 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Wed, 5 May 2010 14:28:53 -0600 Subject: viafb: get rid of i2c debug cruft It's ugly and adds a global.h dependency. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/via_i2c.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index febc1dda69c1..84ec2d6e98c4 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -52,7 +52,7 @@ static void via_i2c_setscl(void *data, int state) val |= 0x80; break; default: - DEBUG_MSG("viafb_i2c: specify wrong i2c type.\n"); + printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n"); } via_write_reg(adap_data->io_port, adap_data->ioport_index, val); spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); @@ -104,7 +104,7 @@ static void via_i2c_setsda(void *data, int state) val |= 0x40; break; default: - DEBUG_MSG("viafb_i2c: specify wrong i2c type.\n"); + printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n"); } via_write_reg(adap_data->io_port, adap_data->ioport_index, val); spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); @@ -175,8 +175,6 @@ static int create_i2c_bus(struct i2c_adapter *adapter, struct via_port_cfg *adap_cfg, struct pci_dev *pdev) { - DEBUG_MSG(KERN_DEBUG "viafb: creating bus adap=0x%p, algo_bit_data=0x%p, adap_cfg=0x%p\n", adapter, algo, adap_cfg); - algo->setsda = via_i2c_setsda; algo->setscl = via_i2c_setscl; algo->getsda = via_i2c_getsda; -- cgit v1.2.3 From 9221fc6556d6fa14b5c61050dd87e26fc4ad255c Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Wed, 5 May 2010 14:24:18 -0600 Subject: viafb: Eliminate some global.h references The various subdev drivers (other than the framebuffer itself) no longer need this file. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/via-gpio.c | 1 - drivers/video/via/via_i2c.c | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c index 63cb7acc0faf..67d699cbfd2c 100644 --- a/drivers/video/via/via-gpio.c +++ b/drivers/video/via/via-gpio.c @@ -10,7 +10,6 @@ #include #include "via-core.h" #include "via-gpio.h" -#include "global.h" /* * The ports we know about. Note that the port-25 gpios are not diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index 84ec2d6e98c4..2291765f2f8e 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -20,9 +20,11 @@ */ #include +#include +#include +#include #include "via-core.h" #include "via_i2c.h" -#include "global.h" /* * There can only be one set of these, so there's no point in having -- cgit v1.2.3 From ec66841e495b9ab4f92bdf91efe8cf56e1471fbd Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Wed, 5 May 2010 14:44:55 -0600 Subject: viafb: move some include files to include/linux These are the files which should be available to subdevices compiled outside of drivers/video/via. Cc: ScottFang@viatech.com.cn Cc: JosephChan@via.com.tw Cc: Harald Welte Acked-by: Florian Tobias Schandinat Signed-off-by: Jonathan Corbet --- drivers/video/via/accel.c | 2 +- drivers/video/via/dvi.c | 4 +- drivers/video/via/hw.c | 3 +- drivers/video/via/lcd.c | 4 +- drivers/video/via/via-core.c | 6 +- drivers/video/via/via-core.h | 219 ------------------------------------ drivers/video/via/via-gpio.c | 4 +- drivers/video/via/via-gpio.h | 14 --- drivers/video/via/via_i2c.c | 4 +- drivers/video/via/via_i2c.h | 42 ------- drivers/video/via/via_modesetting.c | 2 +- drivers/video/via/via_utility.c | 2 +- drivers/video/via/viafbdev.c | 4 +- drivers/video/via/viamode.c | 2 +- drivers/video/via/vt1636.c | 4 +- include/linux/via-core.h | 219 ++++++++++++++++++++++++++++++++++++ include/linux/via-gpio.h | 14 +++ include/linux/via_i2c.h | 42 +++++++ 18 files changed, 296 insertions(+), 295 deletions(-) delete mode 100644 drivers/video/via/via-core.h delete mode 100644 drivers/video/via/via-gpio.h delete mode 100644 drivers/video/via/via_i2c.h create mode 100644 include/linux/via-core.h create mode 100644 include/linux/via-gpio.h create mode 100644 include/linux/via_i2c.h (limited to 'drivers/video') diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index 189aba41f9b9..e44893ea590d 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -18,7 +18,7 @@ * Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "via-core.h" +#include #include "global.h" /* diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c index 6271b7696323..39b040bb3817 100644 --- a/drivers/video/via/dvi.c +++ b/drivers/video/via/dvi.c @@ -18,8 +18,8 @@ * Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "via-core.h" -#include "via_i2c.h" +#include +#include #include "global.h" static void tmds_register_write(int index, u8 data); diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index e356fe8d8a90..b996803ae2c1 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c @@ -18,7 +18,8 @@ * Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "via-core.h" + +#include #include "global.h" static struct pll_map pll_value[] = { diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index 04eec31aa9a2..2ab0f156439a 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c @@ -18,8 +18,8 @@ * Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "via-core.h" -#include "via_i2c.h" +#include +#include #include "global.h" #include "lcdtbl.h" diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index 188c0022dcb4..e8cfe8392110 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c @@ -7,9 +7,9 @@ /* * Core code for the Via multifunction framebuffer device. */ -#include "via-core.h" -#include "via_i2c.h" -#include "via-gpio.h" +#include +#include +#include #include "global.h" #include diff --git a/drivers/video/via/via-core.h b/drivers/video/via/via-core.h deleted file mode 100644 index 7ffb521e1a7a..000000000000 --- a/drivers/video/via/via-core.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. - * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. - * Copyright 2009-2010 Jonathan Corbet - * Copyright 2010 Florian Tobias Schandinat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; - * either version 2, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE.See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __VIA_CORE_H__ -#define __VIA_CORE_H__ -#include -#include -#include -#include - -/* - * A description of each known serial I2C/GPIO port. - */ -enum via_port_type { - VIA_PORT_NONE = 0, - VIA_PORT_I2C, - VIA_PORT_GPIO, -}; - -enum via_port_mode { - VIA_MODE_OFF = 0, - VIA_MODE_I2C, /* Used as I2C port */ - VIA_MODE_GPIO, /* Two GPIO ports */ -}; - -enum viafb_i2c_adap { - VIA_PORT_26 = 0, - VIA_PORT_31, - VIA_PORT_25, - VIA_PORT_2C, - VIA_PORT_3D, -}; -#define VIAFB_NUM_PORTS 5 - -struct via_port_cfg { - enum via_port_type type; - enum via_port_mode mode; - u16 io_port; - u8 ioport_index; -}; - -/* - * This is the global viafb "device" containing stuff needed by - * all subdevs. - */ -struct viafb_dev { - struct pci_dev *pdev; - int chip_type; - struct via_port_cfg *port_cfg; - /* - * Spinlock for access to device registers. Not yet - * globally used. - */ - spinlock_t reg_lock; - /* - * The framebuffer MMIO region. Little, if anything, touches - * this memory directly, and certainly nothing outside of the - * framebuffer device itself. We *do* have to be able to allocate - * chunks of this memory for other devices, though. - */ - unsigned long fbmem_start; - long fbmem_len; - void __iomem *fbmem; -#if defined(CONFIG_FB_VIA_CAMERA) || defined(CONFIG_FB_VIA_CAMERA_MODULE) - long camera_fbmem_offset; - long camera_fbmem_size; -#endif - /* - * The MMIO region for device registers. - */ - unsigned long engine_start; - unsigned long engine_len; - void __iomem *engine_mmio; - -}; - -/* - * Interrupt management. - */ - -void viafb_irq_enable(u32 mask); -void viafb_irq_disable(u32 mask); - -/* - * The global interrupt control register and its bits. - */ -#define VDE_INTERRUPT 0x200 /* Video interrupt flags/masks */ -#define VDE_I_DVISENSE 0x00000001 /* DVI sense int status */ -#define VDE_I_VBLANK 0x00000002 /* Vertical blank status */ -#define VDE_I_MCCFI 0x00000004 /* MCE compl. frame int status */ -#define VDE_I_VSYNC 0x00000008 /* VGA VSYNC int status */ -#define VDE_I_DMA0DDONE 0x00000010 /* DMA 0 descr done */ -#define VDE_I_DMA0TDONE 0x00000020 /* DMA 0 transfer done */ -#define VDE_I_DMA1DDONE 0x00000040 /* DMA 1 descr done */ -#define VDE_I_DMA1TDONE 0x00000080 /* DMA 1 transfer done */ -#define VDE_I_C1AV 0x00000100 /* Cap Eng 1 act vid end */ -#define VDE_I_HQV0 0x00000200 /* First HQV engine */ -#define VDE_I_HQV1 0x00000400 /* Second HQV engine */ -#define VDE_I_HQV1EN 0x00000800 /* Second HQV engine enable */ -#define VDE_I_C0AV 0x00001000 /* Cap Eng 0 act vid end */ -#define VDE_I_C0VBI 0x00002000 /* Cap Eng 0 VBI end */ -#define VDE_I_C1VBI 0x00004000 /* Cap Eng 1 VBI end */ -#define VDE_I_VSYNC2 0x00008000 /* Sec. Disp. VSYNC */ -#define VDE_I_DVISNSEN 0x00010000 /* DVI sense enable */ -#define VDE_I_VSYNC2EN 0x00020000 /* Sec Disp VSYNC enable */ -#define VDE_I_MCCFIEN 0x00040000 /* MC comp frame int mask enable */ -#define VDE_I_VSYNCEN 0x00080000 /* VSYNC enable */ -#define VDE_I_DMA0DDEN 0x00100000 /* DMA 0 descr done enable */ -#define VDE_I_DMA0TDEN 0x00200000 /* DMA 0 trans done enable */ -#define VDE_I_DMA1DDEN 0x00400000 /* DMA 1 descr done enable */ -#define VDE_I_DMA1TDEN 0x00800000 /* DMA 1 trans done enable */ -#define VDE_I_C1AVEN 0x01000000 /* cap 1 act vid end enable */ -#define VDE_I_HQV0EN 0x02000000 /* First hqv engine enable */ -#define VDE_I_C1VBIEN 0x04000000 /* Cap 1 VBI end enable */ -#define VDE_I_LVDSSI 0x08000000 /* LVDS sense interrupt */ -#define VDE_I_C0AVEN 0x10000000 /* Cap 0 act vid end enable */ -#define VDE_I_C0VBIEN 0x20000000 /* Cap 0 VBI end enable */ -#define VDE_I_LVDSSIEN 0x40000000 /* LVDS Sense enable */ -#define VDE_I_ENABLE 0x80000000 /* Global interrupt enable */ - -/* - * DMA management. - */ -int viafb_request_dma(void); -void viafb_release_dma(void); -/* void viafb_dma_copy_out(unsigned int offset, dma_addr_t paddr, int len); */ -int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg); - -/* - * DMA Controller registers. - */ -#define VDMA_MR0 0xe00 /* Mod reg 0 */ -#define VDMA_MR_CHAIN 0x01 /* Chaining mode */ -#define VDMA_MR_TDIE 0x02 /* Transfer done int enable */ -#define VDMA_CSR0 0xe04 /* Control/status */ -#define VDMA_C_ENABLE 0x01 /* DMA Enable */ -#define VDMA_C_START 0x02 /* Start a transfer */ -#define VDMA_C_ABORT 0x04 /* Abort a transfer */ -#define VDMA_C_DONE 0x08 /* Transfer is done */ -#define VDMA_MARL0 0xe20 /* Mem addr low */ -#define VDMA_MARH0 0xe24 /* Mem addr high */ -#define VDMA_DAR0 0xe28 /* Device address */ -#define VDMA_DQWCR0 0xe2c /* Count (16-byte) */ -#define VDMA_TMR0 0xe30 /* Tile mode reg */ -#define VDMA_DPRL0 0xe34 /* Not sure */ -#define VDMA_DPR_IN 0x08 /* Inbound transfer to FB */ -#define VDMA_DPRH0 0xe38 -#define VDMA_PMR0 (0xe00 + 0x134) /* Pitch mode */ - -/* - * Useful stuff that probably belongs somewhere global. - */ -#define VGA_WIDTH 640 -#define VGA_HEIGHT 480 - -/* - * Indexed port operations. Note that these are all multi-op - * functions; every invocation will be racy if you're not holding - * reg_lock. - */ - -#define VIAStatus 0x3DA /* Non-indexed port */ -#define VIACR 0x3D4 -#define VIASR 0x3C4 -#define VIAGR 0x3CE -#define VIAAR 0x3C0 - -static inline u8 via_read_reg(u16 port, u8 index) -{ - outb(index, port); - return inb(port + 1); -} - -static inline void via_write_reg(u16 port, u8 index, u8 data) -{ - outb(index, port); - outb(data, port + 1); -} - -static inline void via_write_reg_mask(u16 port, u8 index, u8 data, u8 mask) -{ - u8 old; - - outb(index, port); - old = inb(port + 1); - outb((data & mask) | (old & ~mask), port + 1); -} - -#define VIA_MISC_REG_READ 0x03CC -#define VIA_MISC_REG_WRITE 0x03C2 - -static inline void via_write_misc_reg_mask(u8 data, u8 mask) -{ - u8 old = inb(VIA_MISC_REG_READ); - outb((data & mask) | (old & ~mask), VIA_MISC_REG_WRITE); -} - - -#endif /* __VIA_CORE_H__ */ diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c index 67d699cbfd2c..595516aea691 100644 --- a/drivers/video/via/via-gpio.c +++ b/drivers/video/via/via-gpio.c @@ -8,8 +8,8 @@ #include #include #include -#include "via-core.h" -#include "via-gpio.h" +#include +#include /* * The ports we know about. Note that the port-25 gpios are not diff --git a/drivers/video/via/via-gpio.h b/drivers/video/via/via-gpio.h deleted file mode 100644 index 8281aea3dd6d..000000000000 --- a/drivers/video/via/via-gpio.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Support for viafb GPIO ports. - * - * Copyright 2009 Jonathan Corbet - * Distributable under version 2 of the GNU General Public License. - */ - -#ifndef __VIA_GPIO_H__ -#define __VIA_GPIO_H__ - -extern int viafb_gpio_lookup(const char *name); -extern int viafb_gpio_init(void); -extern void viafb_gpio_exit(void); -#endif diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index 2291765f2f8e..da9e4ca94b17 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c @@ -23,8 +23,8 @@ #include #include #include -#include "via-core.h" -#include "via_i2c.h" +#include +#include /* * There can only be one set of these, so there's no point in having diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_i2c.h deleted file mode 100644 index 44532e468c05..000000000000 --- a/drivers/video/via/via_i2c.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. - * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. - - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; - * either version 2, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE.See the GNU General Public License - * for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#ifndef __VIA_I2C_H__ -#define __VIA_I2C_H__ - -#include -#include - -struct via_i2c_stuff { - u16 i2c_port; /* GPIO or I2C port */ - u16 is_active; /* Being used as I2C? */ - struct i2c_adapter adapter; - struct i2c_algo_bit_data algo; -}; - - -int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata); -int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data); -int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len); -struct i2c_adapter *viafb_find_i2c_adapter(enum viafb_i2c_adap which); - -extern int viafb_i2c_init(void); -extern void viafb_i2c_exit(void); -#endif /* __VIA_I2C_H__ */ diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c index b4e735cc350e..3cddcff88ab9 100644 --- a/drivers/video/via/via_modesetting.c +++ b/drivers/video/via/via_modesetting.c @@ -24,8 +24,8 @@ */ #include +#include #include "via_modesetting.h" -#include "via-core.h" #include "share.h" #include "debug.h" diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c index 575703141868..d05ccb62b55f 100644 --- a/drivers/video/via/via_utility.c +++ b/drivers/video/via/via_utility.c @@ -19,7 +19,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "via-core.h" +#include #include "global.h" void viafb_get_device_support_state(u32 *support_state) diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 3d033186a822..d3dd2eb95586 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c @@ -22,9 +22,9 @@ #include #include #include -#define _MASTER_FILE +#include -#include "via-core.h" +#define _MASTER_FILE #include "global.h" static char *viafb_name = "Via"; diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index 2fdb9e6724a4..2dbad3c0f679 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c @@ -19,7 +19,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "via-core.h" +#include #include "global.h" struct res_map_refresh res_map_refresh_tbl[] = { /*hres, vres, vclock, vmode_refresh*/ diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c index e5f802472883..d65bf1aee87c 100644 --- a/drivers/video/via/vt1636.c +++ b/drivers/video/via/vt1636.c @@ -19,8 +19,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "via-core.h" -#include "via_i2c.h" +#include +#include #include "global.h" u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information diff --git a/include/linux/via-core.h b/include/linux/via-core.h new file mode 100644 index 000000000000..7ffb521e1a7a --- /dev/null +++ b/include/linux/via-core.h @@ -0,0 +1,219 @@ +/* + * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. + * Copyright 2009-2010 Jonathan Corbet + * Copyright 2010 Florian Tobias Schandinat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; + * either version 2, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE.See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __VIA_CORE_H__ +#define __VIA_CORE_H__ +#include +#include +#include +#include + +/* + * A description of each known serial I2C/GPIO port. + */ +enum via_port_type { + VIA_PORT_NONE = 0, + VIA_PORT_I2C, + VIA_PORT_GPIO, +}; + +enum via_port_mode { + VIA_MODE_OFF = 0, + VIA_MODE_I2C, /* Used as I2C port */ + VIA_MODE_GPIO, /* Two GPIO ports */ +}; + +enum viafb_i2c_adap { + VIA_PORT_26 = 0, + VIA_PORT_31, + VIA_PORT_25, + VIA_PORT_2C, + VIA_PORT_3D, +}; +#define VIAFB_NUM_PORTS 5 + +struct via_port_cfg { + enum via_port_type type; + enum via_port_mode mode; + u16 io_port; + u8 ioport_index; +}; + +/* + * This is the global viafb "device" containing stuff needed by + * all subdevs. + */ +struct viafb_dev { + struct pci_dev *pdev; + int chip_type; + struct via_port_cfg *port_cfg; + /* + * Spinlock for access to device registers. Not yet + * globally used. + */ + spinlock_t reg_lock; + /* + * The framebuffer MMIO region. Little, if anything, touches + * this memory directly, and certainly nothing outside of the + * framebuffer device itself. We *do* have to be able to allocate + * chunks of this memory for other devices, though. + */ + unsigned long fbmem_start; + long fbmem_len; + void __iomem *fbmem; +#if defined(CONFIG_FB_VIA_CAMERA) || defined(CONFIG_FB_VIA_CAMERA_MODULE) + long camera_fbmem_offset; + long camera_fbmem_size; +#endif + /* + * The MMIO region for device registers. + */ + unsigned long engine_start; + unsigned long engine_len; + void __iomem *engine_mmio; + +}; + +/* + * Interrupt management. + */ + +void viafb_irq_enable(u32 mask); +void viafb_irq_disable(u32 mask); + +/* + * The global interrupt control register and its bits. + */ +#define VDE_INTERRUPT 0x200 /* Video interrupt flags/masks */ +#define VDE_I_DVISENSE 0x00000001 /* DVI sense int status */ +#define VDE_I_VBLANK 0x00000002 /* Vertical blank status */ +#define VDE_I_MCCFI 0x00000004 /* MCE compl. frame int status */ +#define VDE_I_VSYNC 0x00000008 /* VGA VSYNC int status */ +#define VDE_I_DMA0DDONE 0x00000010 /* DMA 0 descr done */ +#define VDE_I_DMA0TDONE 0x00000020 /* DMA 0 transfer done */ +#define VDE_I_DMA1DDONE 0x00000040 /* DMA 1 descr done */ +#define VDE_I_DMA1TDONE 0x00000080 /* DMA 1 transfer done */ +#define VDE_I_C1AV 0x00000100 /* Cap Eng 1 act vid end */ +#define VDE_I_HQV0 0x00000200 /* First HQV engine */ +#define VDE_I_HQV1 0x00000400 /* Second HQV engine */ +#define VDE_I_HQV1EN 0x00000800 /* Second HQV engine enable */ +#define VDE_I_C0AV 0x00001000 /* Cap Eng 0 act vid end */ +#define VDE_I_C0VBI 0x00002000 /* Cap Eng 0 VBI end */ +#define VDE_I_C1VBI 0x00004000 /* Cap Eng 1 VBI end */ +#define VDE_I_VSYNC2 0x00008000 /* Sec. Disp. VSYNC */ +#define VDE_I_DVISNSEN 0x00010000 /* DVI sense enable */ +#define VDE_I_VSYNC2EN 0x00020000 /* Sec Disp VSYNC enable */ +#define VDE_I_MCCFIEN 0x00040000 /* MC comp frame int mask enable */ +#define VDE_I_VSYNCEN 0x00080000 /* VSYNC enable */ +#define VDE_I_DMA0DDEN 0x00100000 /* DMA 0 descr done enable */ +#define VDE_I_DMA0TDEN 0x00200000 /* DMA 0 trans done enable */ +#define VDE_I_DMA1DDEN 0x00400000 /* DMA 1 descr done enable */ +#define VDE_I_DMA1TDEN 0x00800000 /* DMA 1 trans done enable */ +#define VDE_I_C1AVEN 0x01000000 /* cap 1 act vid end enable */ +#define VDE_I_HQV0EN 0x02000000 /* First hqv engine enable */ +#define VDE_I_C1VBIEN 0x04000000 /* Cap 1 VBI end enable */ +#define VDE_I_LVDSSI 0x08000000 /* LVDS sense interrupt */ +#define VDE_I_C0AVEN 0x10000000 /* Cap 0 act vid end enable */ +#define VDE_I_C0VBIEN 0x20000000 /* Cap 0 VBI end enable */ +#define VDE_I_LVDSSIEN 0x40000000 /* LVDS Sense enable */ +#define VDE_I_ENABLE 0x80000000 /* Global interrupt enable */ + +/* + * DMA management. + */ +int viafb_request_dma(void); +void viafb_release_dma(void); +/* void viafb_dma_copy_out(unsigned int offset, dma_addr_t paddr, int len); */ +int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg); + +/* + * DMA Controller registers. + */ +#define VDMA_MR0 0xe00 /* Mod reg 0 */ +#define VDMA_MR_CHAIN 0x01 /* Chaining mode */ +#define VDMA_MR_TDIE 0x02 /* Transfer done int enable */ +#define VDMA_CSR0 0xe04 /* Control/status */ +#define VDMA_C_ENABLE 0x01 /* DMA Enable */ +#define VDMA_C_START 0x02 /* Start a transfer */ +#define VDMA_C_ABORT 0x04 /* Abort a transfer */ +#define VDMA_C_DONE 0x08 /* Transfer is done */ +#define VDMA_MARL0 0xe20 /* Mem addr low */ +#define VDMA_MARH0 0xe24 /* Mem addr high */ +#define VDMA_DAR0 0xe28 /* Device address */ +#define VDMA_DQWCR0 0xe2c /* Count (16-byte) */ +#define VDMA_TMR0 0xe30 /* Tile mode reg */ +#define VDMA_DPRL0 0xe34 /* Not sure */ +#define VDMA_DPR_IN 0x08 /* Inbound transfer to FB */ +#define VDMA_DPRH0 0xe38 +#define VDMA_PMR0 (0xe00 + 0x134) /* Pitch mode */ + +/* + * Useful stuff that probably belongs somewhere global. + */ +#define VGA_WIDTH 640 +#define VGA_HEIGHT 480 + +/* + * Indexed port operations. Note that these are all multi-op + * functions; every invocation will be racy if you're not holding + * reg_lock. + */ + +#define VIAStatus 0x3DA /* Non-indexed port */ +#define VIACR 0x3D4 +#define VIASR 0x3C4 +#define VIAGR 0x3CE +#define VIAAR 0x3C0 + +static inline u8 via_read_reg(u16 port, u8 index) +{ + outb(index, port); + return inb(port + 1); +} + +static inline void via_write_reg(u16 port, u8 index, u8 data) +{ + outb(index, port); + outb(data, port + 1); +} + +static inline void via_write_reg_mask(u16 port, u8 index, u8 data, u8 mask) +{ + u8 old; + + outb(index, port); + old = inb(port + 1); + outb((data & mask) | (old & ~mask), port + 1); +} + +#define VIA_MISC_REG_READ 0x03CC +#define VIA_MISC_REG_WRITE 0x03C2 + +static inline void via_write_misc_reg_mask(u8 data, u8 mask) +{ + u8 old = inb(VIA_MISC_REG_READ); + outb((data & mask) | (old & ~mask), VIA_MISC_REG_WRITE); +} + + +#endif /* __VIA_CORE_H__ */ diff --git a/include/linux/via-gpio.h b/include/linux/via-gpio.h new file mode 100644 index 000000000000..8281aea3dd6d --- /dev/null +++ b/include/linux/via-gpio.h @@ -0,0 +1,14 @@ +/* + * Support for viafb GPIO ports. + * + * Copyright 2009 Jonathan Corbet + * Distributable under version 2 of the GNU General Public License. + */ + +#ifndef __VIA_GPIO_H__ +#define __VIA_GPIO_H__ + +extern int viafb_gpio_lookup(const char *name); +extern int viafb_gpio_init(void); +extern void viafb_gpio_exit(void); +#endif diff --git a/include/linux/via_i2c.h b/include/linux/via_i2c.h new file mode 100644 index 000000000000..44532e468c05 --- /dev/null +++ b/include/linux/via_i2c.h @@ -0,0 +1,42 @@ +/* + * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. + + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; + * either version 2, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE.See the GNU General Public License + * for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef __VIA_I2C_H__ +#define __VIA_I2C_H__ + +#include +#include + +struct via_i2c_stuff { + u16 i2c_port; /* GPIO or I2C port */ + u16 is_active; /* Being used as I2C? */ + struct i2c_adapter adapter; + struct i2c_algo_bit_data algo; +}; + + +int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata); +int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data); +int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len); +struct i2c_adapter *viafb_find_i2c_adapter(enum viafb_i2c_adap which); + +extern int viafb_i2c_init(void); +extern void viafb_i2c_exit(void); +#endif /* __VIA_I2C_H__ */ -- cgit v1.2.3 From de145b44b95b9d3212a82d1c0f29b09778ef33c5 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 11 May 2010 14:07:00 -0700 Subject: fbdev: bfin-t350mcqb-fb: fix fbmem allocation with blanking lines The current allocation does not include the memory required for blanking lines. So avoid memory corruption when multiple devices are using the DMA memory near each other. Signed-off-by: Michael Hennerich Signed-off-by: Mike Frysinger Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/bfin-t350mcqb-fb.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index 44e49c28b2a7..c2ec3dcd4e91 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c @@ -488,9 +488,9 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) fbinfo->fbops = &bfin_t350mcqb_fb_ops; fbinfo->flags = FBINFO_FLAG_DEFAULT; - info->fb_buffer = - dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle, - GFP_KERNEL); + info->fb_buffer = dma_alloc_coherent(NULL, fbinfo->fix.smem_len + + ACTIVE_VIDEO_MEM_OFFSET, + &info->dma_handle, GFP_KERNEL); if (NULL == info->fb_buffer) { printk(KERN_ERR DRIVER_NAME @@ -568,8 +568,8 @@ out7: out6: fb_dealloc_cmap(&fbinfo->cmap); out4: - dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, - info->dma_handle); + dma_free_coherent(NULL, fbinfo->fix.smem_len + ACTIVE_VIDEO_MEM_OFFSET, + info->fb_buffer, info->dma_handle); out3: framebuffer_release(fbinfo); out2: @@ -592,8 +592,9 @@ static int __devexit bfin_t350mcqb_remove(struct platform_device *pdev) free_irq(info->irq, info); if (info->fb_buffer != NULL) - dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, - info->dma_handle); + dma_free_coherent(NULL, fbinfo->fix.smem_len + + ACTIVE_VIDEO_MEM_OFFSET, info->fb_buffer, + info->dma_handle); fb_dealloc_cmap(&fbinfo->cmap); -- cgit v1.2.3 From bf54a2b3c0dbf76136f00ff785bf6d8f6291311d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Nov 2008 21:13:53 +0100 Subject: m68k: amiga - Zorro bus modalias support Add Amiga Zorro bus modalias and uevent support Signed-off-by: Geert Uytterhoeven --- drivers/net/a2065.c | 1 + drivers/net/ariadne.c | 1 + drivers/net/hydra.c | 1 + drivers/net/zorro8390.c | 1 + drivers/scsi/zorro7xx.c | 1 + drivers/video/cirrusfb.c | 1 + drivers/video/fm2fb.c | 1 + drivers/zorro/zorro-driver.c | 24 ++++++++++++++++++++++++ drivers/zorro/zorro-sysfs.c | 11 +++++++++++ include/linux/mod_devicetable.h | 9 +++++++++ include/linux/zorro.h | 13 +------------ scripts/mod/file2alias.c | 14 ++++++++++++++ 12 files changed, 66 insertions(+), 12 deletions(-) (limited to 'drivers/video') diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index ed5e9742be2c..a8f0512bad38 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -674,6 +674,7 @@ static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = { { ZORRO_PROD_AMERISTAR_A2065 }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, a2065_zorro_tbl); static struct zorro_driver a2065_driver = { .name = "a2065", diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index fa1a2354f5f9..4b30a46486e2 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -145,6 +145,7 @@ static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = { { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl); static struct zorro_driver ariadne_driver = { .name = "ariadne", diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 24724b4ad709..07d8e5b634f3 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -71,6 +71,7 @@ static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = { { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, hydra_zorro_tbl); static struct zorro_driver hydra_driver = { .name = "hydra", diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index 81c753a617ab..9548cbb5012a 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c @@ -102,6 +102,7 @@ static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = { { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl); static struct zorro_driver zorro8390_driver = { .name = "zorro8390", diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index 105449c15fa9..e17764d71476 100644 --- a/drivers/scsi/zorro7xx.c +++ b/drivers/scsi/zorro7xx.c @@ -69,6 +69,7 @@ static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = { }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl); static int __devinit zorro7xx_init_one(struct zorro_dev *z, const struct zorro_device_id *ent) diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 8d8dfda2f868..6df7c54db0a3 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -299,6 +299,7 @@ static const struct zorro_device_id cirrusfb_zorro_table[] = { }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table); static const struct { zorro_id id2; diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index 6c91c61cdb63..1b0feb8e7244 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -219,6 +219,7 @@ static struct zorro_device_id fm2fb_devices[] __devinitdata = { { ZORRO_PROD_HELFRICH_RAINBOW_II }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, fm2fb_devices); static struct zorro_driver fm2fb_driver = { .name = "fm2fb", diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index 53180a37cc9a..7ee2b6e71786 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c @@ -137,10 +137,34 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv) return 0; } +static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env) +{ +#ifdef CONFIG_HOTPLUG + struct zorro_dev *z; + + if (!dev) + return -ENODEV; + + z = to_zorro_dev(dev); + if (!z) + return -ENODEV; + + if (add_uevent_var(env, "ZORRO_ID=%08X", z->id) || + add_uevent_var(env, "ZORRO_SLOT_NAME=%s", dev_name(dev)) || + add_uevent_var(env, "ZORRO_SLOT_ADDR=%04X", z->slotaddr) || + add_uevent_var(env, "MODALIAS=" ZORRO_DEVICE_MODALIAS_FMT, z->id)) + return -ENOMEM; + + return 0; +#else /* !CONFIG_HOTPLUG */ + return -ENODEV; +#endif /* !CONFIG_HOTPLUG */ +} struct bus_type zorro_bus_type = { .name = "zorro", .match = zorro_bus_match, + .uevent = zorro_uevent, .probe = zorro_device_probe, .remove = zorro_device_remove, }; diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index 1d2a772ea14c..eb924e0a64ce 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c @@ -77,6 +77,16 @@ static struct bin_attribute zorro_config_attr = { .read = zorro_read_config, }; +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct zorro_dev *z = to_zorro_dev(dev); + + return sprintf(buf, ZORRO_DEVICE_MODALIAS_FMT "\n", z->id); +} + +static DEVICE_ATTR(modalias, S_IRUGO, modalias_show, NULL); + int zorro_create_sysfs_dev_files(struct zorro_dev *z) { struct device *dev = &z->dev; @@ -89,6 +99,7 @@ int zorro_create_sysfs_dev_files(struct zorro_dev *z) (error = device_create_file(dev, &dev_attr_slotaddr)) || (error = device_create_file(dev, &dev_attr_slotsize)) || (error = device_create_file(dev, &dev_attr_resource)) || + (error = device_create_file(dev, &dev_attr_modalias)) || (error = sysfs_create_bin_file(&dev->kobj, &zorro_config_attr))) return error; diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index f58e9d836f32..56fde4364e4c 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -474,4 +474,13 @@ struct platform_device_id { __attribute__((aligned(sizeof(kernel_ulong_t)))); }; +struct zorro_device_id { + __u32 id; /* Device ID or ZORRO_WILDCARD */ + kernel_ulong_t driver_data; /* Data private to the driver */ +}; + +#define ZORRO_WILDCARD (0xffffffff) /* not official */ + +#define ZORRO_DEVICE_MODALIAS_FMT "zorro:i%08X" + #endif /* LINUX_MOD_DEVICETABLE_H */ diff --git a/include/linux/zorro.h b/include/linux/zorro.h index 913bfc226dda..908db1b36d6c 100644 --- a/include/linux/zorro.h +++ b/include/linux/zorro.h @@ -38,8 +38,6 @@ typedef __u32 zorro_id; -#define ZORRO_WILDCARD (0xffffffff) /* not official */ - /* Include the ID list */ #include @@ -116,6 +114,7 @@ struct ConfigDev { #include #include +#include #include @@ -154,16 +153,6 @@ extern struct zorro_bus zorro_bus; /* single Zorro bus */ extern struct bus_type zorro_bus_type; - /* - * Zorro device IDs - */ - -struct zorro_device_id { - zorro_id id; /* Device ID or ZORRO_WILDCARD */ - unsigned long driver_data; /* Data private to the driver */ -}; - - /* * Zorro device drivers */ diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 220213e603db..df90f31d14bf 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -796,6 +796,16 @@ static int do_platform_entry(const char *filename, return 1; } +/* Looks like: zorro:iN. */ +static int do_zorro_entry(const char *filename, struct zorro_device_id *id, + char *alias) +{ + id->id = TO_NATIVE(id->id); + strcpy(alias, "zorro:"); + ADD(alias, "i", id->id != ZORRO_WILDCARD, id->id); + return 1; +} + /* Ignore any prefix, eg. some architectures prepend _ */ static inline int sym_is(const char *symbol, const char *name) { @@ -943,6 +953,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, do_table(symval, sym->st_size, sizeof(struct platform_device_id), "platform", do_platform_entry, mod); + else if (sym_is(symname, "__mod_zorro_device_table")) + do_table(symval, sym->st_size, + sizeof(struct zorro_device_id), "zorro", + do_zorro_entry, mod); free(zeros); } -- cgit v1.2.3 From fa6688e1c7e7341fb7d1ca5878a3641762e60dec Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 5 Apr 2009 12:45:56 +0200 Subject: m68k: amiga - Frame buffer platform device conversion Signed-off-by: Geert Uytterhoeven --- arch/m68k/amiga/platform.c | 15 ++++++++++++++ drivers/video/amifb.c | 49 +++++++++++++++++++++++++++++----------------- 2 files changed, 46 insertions(+), 18 deletions(-) (limited to 'drivers/video') diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 33a7669b4415..7fa929cf9a3a 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -56,3 +56,18 @@ static int __init amiga_init_bus(void) subsys_initcall(amiga_init_bus); #endif /* CONFIG_ZORRO */ + + +static int __init amiga_init_devices(void) +{ + if (!MACH_IS_AMIGA) + return -ENODEV; + + /* video hardware */ + if (AMIGAHW_PRESENT(AMI_VIDEO)) + platform_device_register_simple("amiga-video", -1, NULL, 0); + + return 0; +} + +device_initcall(amiga_init_devices); diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index dca48df98444..e5d6b56d4447 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -50,8 +50,9 @@ #include #include #include - +#include #include + #include #include #include @@ -1135,7 +1136,7 @@ static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg * Interface to the low level console driver */ -static void amifb_deinit(void); +static void amifb_deinit(struct platform_device *pdev); /* * Internal routines @@ -2246,7 +2247,7 @@ static inline void chipfree(void) * Initialisation */ -static int __init amifb_init(void) +static int __init amifb_probe(struct platform_device *pdev) { int tag, i, err = 0; u_long chipptr; @@ -2261,16 +2262,6 @@ static int __init amifb_init(void) } amifb_setup(option); #endif - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO)) - return -ENODEV; - - /* - * We request all registers starting from bplpt[0] - */ - if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120, - "amifb [Denise/Lisa]")) - return -EBUSY; - custom.dmacon = DMAF_ALL | DMAF_MASTER; switch (amiga_chipset) { @@ -2377,6 +2368,7 @@ default_chipset: fb_info.fbops = &amifb_ops; fb_info.par = ¤tpar; fb_info.flags = FBINFO_DEFAULT; + fb_info.device = &pdev->dev; if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { @@ -2451,18 +2443,18 @@ default_chipset: return 0; amifb_error: - amifb_deinit(); + amifb_deinit(pdev); return err; } -static void amifb_deinit(void) +static void amifb_deinit(struct platform_device *pdev) { if (fb_info.cmap.len) fb_dealloc_cmap(&fb_info.cmap); + fb_dealloc_cmap(&fb_info.cmap); chipfree(); if (videomemory) iounmap((void*)videomemory); - release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120); custom.dmacon = DMAF_ALL | DMAF_MASTER; } @@ -3794,14 +3786,35 @@ static void ami_rebuild_copper(void) } } -static void __exit amifb_exit(void) +static int __exit amifb_remove(struct platform_device *pdev) { unregister_framebuffer(&fb_info); - amifb_deinit(); + amifb_deinit(pdev); amifb_video_off(); + return 0; +} + +static struct platform_driver amifb_driver = { + .remove = __exit_p(amifb_remove), + .driver = { + .name = "amiga-video", + .owner = THIS_MODULE, + }, +}; + +static int __init amifb_init(void) +{ + return platform_driver_probe(&amifb_driver, amifb_probe); } module_init(amifb_init); + +static void __exit amifb_exit(void) +{ + platform_driver_unregister(&amifb_driver); +} + module_exit(amifb_exit); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-video"); -- cgit v1.2.3 From 058276303dbc4ed089c1f7dad0871810b1f5ddf1 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 17 May 2010 16:30:42 -0700 Subject: DMAENGINE: extend the control command to include an arg This adds an argument to the DMAengine control function, so that we can later provide control commands that need some external data passed in through an argument akin to the ioctl() operation prototype. [dan.j.williams@intel.com: fix up some missed conversions] Signed-off-by: Linus Walleij Signed-off-by: Dan Williams --- drivers/dma/at_hdmac.c | 3 ++- drivers/dma/coh901318.c | 5 +++-- drivers/dma/dw_dmac.c | 3 ++- drivers/dma/fsldma.c | 2 +- drivers/dma/ipu/ipu_idmac.c | 12 +++++++----- drivers/dma/shdma.c | 3 ++- drivers/dma/ste_dma40.c | 3 ++- drivers/dma/timb_dma.c | 3 ++- drivers/dma/txx9dmac.c | 3 ++- drivers/mmc/host/atmel-mci.c | 2 +- drivers/serial/sh-sci.c | 2 +- drivers/video/mx3fb.c | 2 +- include/linux/dmaengine.h | 3 ++- sound/soc/txx9/txx9aclc.c | 7 ++++--- 14 files changed, 32 insertions(+), 21 deletions(-) (limited to 'drivers/video') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 93ed99c84cf1..ee805a43f879 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -759,7 +759,8 @@ err_desc_get: return NULL; } -static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd) +static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) { struct at_dma_chan *atchan = to_at_dma_chan(chan); struct at_dma *atdma = to_at_dma(chan->device); diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c index 4233440741a2..a724e6be1b4d 100644 --- a/drivers/dma/coh901318.c +++ b/drivers/dma/coh901318.c @@ -942,7 +942,7 @@ coh901318_free_chan_resources(struct dma_chan *chan) spin_unlock_irqrestore(&cohc->lock, flags); - chan->device->device_control(chan, DMA_TERMINATE_ALL); + chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); } @@ -1176,7 +1176,8 @@ coh901318_issue_pending(struct dma_chan *chan) } static int -coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd) +coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) { unsigned long flags; struct coh901318_chan *cohc = to_coh901318_chan(chan); diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 18fb5b41cedf..a3991ab0d67e 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -781,7 +781,8 @@ err_desc_get: return NULL; } -static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd) +static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct dw_dma *dw = to_dw_dma(chan->device); diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index cb1924f46c9e..005329d496bd 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -775,7 +775,7 @@ fail: } static int fsl_dma_device_control(struct dma_chan *dchan, - enum dma_ctrl_cmd cmd) + enum dma_ctrl_cmd cmd, unsigned long arg) { struct fsldma_chan *chan; unsigned long flags; diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index 246a6143e4a7..cb26ee9773d6 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -1472,7 +1472,8 @@ static void idmac_issue_pending(struct dma_chan *chan) */ } -static int __idmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd) +static int __idmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) { struct idmac_channel *ichan = to_idmac_chan(chan); struct idmac *idmac = to_idmac(chan->device); @@ -1513,14 +1514,15 @@ static int __idmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd) return 0; } -static int idmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd) +static int idmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) { struct idmac_channel *ichan = to_idmac_chan(chan); int ret; mutex_lock(&ichan->chan_mutex); - ret = __idmac_control(chan, cmd); + ret = __idmac_control(chan, cmd, arg); mutex_unlock(&ichan->chan_mutex); @@ -1616,7 +1618,7 @@ static void idmac_free_chan_resources(struct dma_chan *chan) mutex_lock(&ichan->chan_mutex); - __idmac_control(chan, DMA_TERMINATE_ALL); + __idmac_control(chan, DMA_TERMINATE_ALL, 0); if (ichan->status > IPU_CHANNEL_FREE) { #ifdef DEBUG @@ -1709,7 +1711,7 @@ static void __exit ipu_idmac_exit(struct ipu *ipu) for (i = 0; i < IPU_CHANNELS_NUM; i++) { struct idmac_channel *ichan = ipu->channel + i; - idmac_control(&ichan->dma_chan, DMA_TERMINATE_ALL); + idmac_control(&ichan->dma_chan, DMA_TERMINATE_ALL, 0); idmac_prep_slave_sg(&ichan->dma_chan, NULL, 0, DMA_NONE, 0); } diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 98f82cdb404c..e9de1d35c20d 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -580,7 +580,8 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( direction, flags); } -static int sh_dmae_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd) +static int sh_dmae_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) { struct sh_dmae_chan *sh_chan = to_sh_chan(chan); diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 81fec95312b6..c426829f6ab8 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -2065,7 +2065,8 @@ static void d40_issue_pending(struct dma_chan *chan) spin_unlock_irqrestore(&d40c->lock, flags); } -static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd) +static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) { unsigned long flags; struct d40_chan *d40c = container_of(chan, struct d40_chan, chan); diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c index 44b346d8d319..0172fa3c7a2b 100644 --- a/drivers/dma/timb_dma.c +++ b/drivers/dma/timb_dma.c @@ -611,7 +611,8 @@ static struct dma_async_tx_descriptor *td_prep_slave_sg(struct dma_chan *chan, return &td_desc->txd; } -static int td_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd) +static int td_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) { struct timb_dma_chan *td_chan = container_of(chan, struct timb_dma_chan, chan); diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c index e523737639aa..d02edb05910e 100644 --- a/drivers/dma/txx9dmac.c +++ b/drivers/dma/txx9dmac.c @@ -938,7 +938,8 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, return &first->txd; } -static int txx9dmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd) +static int txx9dmac_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg) { struct txx9dmac_chan *dc = to_txx9dmac_chan(chan); struct txx9dmac_desc *desc, *_desc; diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index ae6d24ba4f08..fd2d24f81478 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -578,7 +578,7 @@ static void atmci_stop_dma(struct atmel_mci *host) struct dma_chan *chan = host->data_chan; if (chan) { - chan->device->device_control(chan, DMA_TERMINATE_ALL); + chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); atmci_dma_cleanup(host); } else { /* Data transfer was stopped by the interrupt handler */ diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 690988237971..882f3d5ed028 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -1087,7 +1087,7 @@ static void work_fn_rx(struct work_struct *work) unsigned long flags; int count; - chan->device->device_control(chan, DMA_TERMINATE_ALL); + chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); dev_dbg(port->dev, "Read %u bytes with cookie %d\n", sh_desc->partial, sh_desc->cookie); diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 3aa50bc276eb..7cfc170bce19 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -388,7 +388,7 @@ static void sdc_disable_channel(struct mx3fb_info *mx3_fbi) spin_unlock_irqrestore(&mx3fb->lock, flags); mx3_fbi->txd->chan->device->device_control(mx3_fbi->txd->chan, - DMA_TERMINATE_ALL); + DMA_TERMINATE_ALL, 0); mx3_fbi->txd = NULL; mx3_fbi->cookie = -EINVAL; } diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 50b7b3e0d572..17456571ff7a 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -347,7 +347,8 @@ struct dma_device { struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_data_direction direction, unsigned long flags); - int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd); + int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + unsigned long arg); enum dma_status (*device_tx_status)(struct dma_chan *chan, dma_cookie_t cookie, diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c index b35d00706c0e..9398f507f77f 100644 --- a/sound/soc/txx9/txx9aclc.c +++ b/sound/soc/txx9/txx9aclc.c @@ -159,7 +159,7 @@ static void txx9aclc_dma_tasklet(unsigned long data) void __iomem *base = drvdata->base; spin_unlock_irqrestore(&dmadata->dma_lock, flags); - chan->device->device_control(chan, DMA_TERMINATE_ALL); + chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); /* first time */ for (i = 0; i < NR_DMA_CHAIN; i++) { desc = txx9aclc_dma_submit(dmadata, @@ -267,7 +267,7 @@ static int txx9aclc_pcm_close(struct snd_pcm_substream *substream) struct dma_chan *chan = dmadata->dma_chan; dmadata->frag_count = -1; - chan->device->device_control(chan, DMA_TERMINATE_ALL); + chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); return 0; } @@ -396,7 +396,8 @@ static int txx9aclc_pcm_remove(struct platform_device *pdev) struct dma_chan *chan = dmadata->dma_chan; if (chan) { dmadata->frag_count = -1; - chan->device->device_control(chan, DMA_TERMINATE_ALL); + chan->device->device_control(chan, + DMA_TERMINATE_ALL, 0); dma_release_channel(chan); } dev->dmadata[i].dma_chan = NULL; -- cgit v1.2.3 From 1471ca9aa71cd37b6a7476bb6f06a3a8622ea1bd Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sun, 16 May 2010 17:27:03 +0200 Subject: fbdev: allow passing more than one aperture for handoff It removes a hack from nouveau code which had to detect which region to pass to kick vesafb/efifb. Signed-off-by: Marcin Slusarz Cc: Eric Anholt Cc: Ben Skeggs Cc: Thomas Hellstrom Cc: Dave Airlie Cc: Peter Jones Cc: Benjamin Herrenschmidt Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/intel_fb.c | 11 +++-- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 84 ++++++++++----------------------- drivers/gpu/drm/radeon/radeon_fb.c | 9 +++- drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 10 +++- drivers/video/efifb.c | 11 +++-- drivers/video/fbmem.c | 29 ++++++++++-- drivers/video/fbsysfs.c | 1 + drivers/video/offb.c | 28 ++++++----- drivers/video/vesafb.c | 11 +++-- include/linux/fb.h | 17 ++++++- 10 files changed, 123 insertions(+), 88 deletions(-) (limited to 'drivers/video') diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index b04e0a86bf9a..7f1eabbaa2bb 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -128,11 +128,16 @@ static int intelfb_create(struct intel_fbdev *ifbdev, info->fbops = &intelfb_ops; /* setup aperture base/size for vesafb takeover */ - info->aperture_base = dev->mode_config.fb_base; + info->apertures = alloc_apertures(1); + if (!info->apertures) { + ret = -ENOMEM; + goto out_unpin; + } + info->apertures->ranges[0].base = dev->mode_config.fb_base; if (IS_I9XX(dev)) - info->aperture_size = pci_resource_len(dev->pdev, 2); + info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 2); else - info->aperture_size = pci_resource_len(dev->pdev, 0); + info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0); info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; info->fix.smem_len = size; diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index f29fa8c117ce..292c7ff95105 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -152,44 +152,6 @@ static void nouveau_fbcon_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, *blue = nv_crtc->lut.b[regno]; } -#if defined(__i386__) || defined(__x86_64__) -static bool -nouveau_fbcon_has_vesafb_or_efifb(struct drm_device *dev) -{ - struct pci_dev *pdev = dev->pdev; - int ramin; - - if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB && - screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) - return false; - - if (screen_info.lfb_base < pci_resource_start(pdev, 1)) - goto not_fb; - - if (screen_info.lfb_base + screen_info.lfb_size >= - pci_resource_start(pdev, 1) + pci_resource_len(pdev, 1)) - goto not_fb; - - return true; -not_fb: - ramin = 2; - if (pci_resource_len(pdev, ramin) == 0) { - ramin = 3; - if (pci_resource_len(pdev, ramin) == 0) - return false; - } - - if (screen_info.lfb_base < pci_resource_start(pdev, ramin)) - return false; - - if (screen_info.lfb_base + screen_info.lfb_size >= - pci_resource_start(pdev, ramin) + pci_resource_len(pdev, ramin)) - return false; - - return true; -} -#endif - static void nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *nfbdev) { @@ -219,7 +181,9 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, struct nouveau_framebuffer *nouveau_fb; struct nouveau_bo *nvbo; struct drm_mode_fb_cmd mode_cmd; - struct device *device = &dev->pdev->dev; + struct pci_dev *pdev = dev->pdev; + struct device *device = &pdev->dev; + struct apertures_struct *aper; int size, ret; mode_cmd.width = sizes->surface_width; @@ -299,28 +263,30 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, drm_fb_helper_fill_var(info, &nfbdev->helper, sizes->fb_width, sizes->fb_height); /* FIXME: we really shouldn't expose mmio space at all */ - info->fix.mmio_start = pci_resource_start(dev->pdev, 1); - info->fix.mmio_len = pci_resource_len(dev->pdev, 1); + info->fix.mmio_start = pci_resource_start(pdev, 1); + info->fix.mmio_len = pci_resource_len(pdev, 1); /* Set aperture base/size for vesafb takeover */ -#if defined(__i386__) || defined(__x86_64__) - if (nouveau_fbcon_has_vesafb_or_efifb(dev)) { - /* Some NVIDIA VBIOS' are stupid and decide to put the - * framebuffer in the middle of the PRAMIN BAR for - * whatever reason. We need to know the exact lfb_base - * to get vesafb kicked off, and the only reliable way - * we have left is to find out lfb_base the same way - * vesafb did. - */ - info->aperture_base = screen_info.lfb_base; - info->aperture_size = screen_info.lfb_size; - if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB) - info->aperture_size *= 65536; - } else -#endif - { - info->aperture_base = info->fix.mmio_start; - info->aperture_size = info->fix.mmio_len; + aper = info->apertures = alloc_apertures(3); + if (!info->apertures) { + ret = -ENOMEM; + goto out_unref; + } + + aper->ranges[0].base = pci_resource_start(pdev, 1); + aper->ranges[0].size = pci_resource_len(pdev, 1); + aper->count = 1; + + if (pci_resource_len(pdev, 2)) { + aper->ranges[aper->count].base = pci_resource_start(pdev, 2); + aper->ranges[aper->count].size = pci_resource_len(pdev, 2); + aper->count++; + } + + if (pci_resource_len(pdev, 3)) { + aper->ranges[aper->count].base = pci_resource_start(pdev, 3); + aper->ranges[aper->count].size = pci_resource_len(pdev, 3); + aper->count++; } info->pixmap.size = 64*1024; diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index fcb5b52727b0..b4948021e345 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -236,8 +236,13 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev, drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height); /* setup aperture base/size for vesafb takeover */ - info->aperture_base = rdev->ddev->mode_config.fb_base; - info->aperture_size = rdev->mc.real_vram_size; + info->apertures = alloc_apertures(1); + if (!info->apertures) { + ret = -ENOMEM; + goto out_unref; + } + info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base; + info->apertures->ranges[0].size = rdev->mc.real_vram_size; info->fix.mmio_start = 0; info->fix.mmio_len = 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 80125ffc4e28..7421aaad8d09 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -559,8 +559,13 @@ int vmw_fb_init(struct vmw_private *vmw_priv) info->pixmap.scan_align = 1; #endif - info->aperture_base = vmw_priv->vram_start; - info->aperture_size = vmw_priv->vram_size; + info->apertures = alloc_apertures(1); + if (!info->apertures) { + ret = -ENOMEM; + goto err_aper; + } + info->apertures->ranges[0].base = vmw_priv->vram_start; + info->apertures->ranges[0].size = vmw_priv->vram_size; /* * Dirty & Deferred IO @@ -580,6 +585,7 @@ int vmw_fb_init(struct vmw_private *vmw_priv) err_defio: fb_deferred_io_cleanup(info); +err_aper: ttm_bo_kunmap(&par->map); err_unref: ttm_bo_unref((struct ttm_buffer_object **)&par->vmw_bo); diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 581d2dbf675a..3b986567111a 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -165,7 +165,7 @@ static void efifb_destroy(struct fb_info *info) { if (info->screen_base) iounmap(info->screen_base); - release_mem_region(info->aperture_base, info->aperture_size); + release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); framebuffer_release(info); } @@ -289,8 +289,13 @@ static int __devinit efifb_probe(struct platform_device *dev) info->pseudo_palette = info->par; info->par = NULL; - info->aperture_base = efifb_fix.smem_start; - info->aperture_size = size_remap; + info->apertures = alloc_apertures(1); + if (!info->apertures) { + err = -ENOMEM; + goto err_release_fb; + } + info->apertures->ranges[0].base = efifb_fix.smem_start; + info->apertures->ranges[0].size = size_remap; info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); if (!info->screen_base) { diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index a15b44e9c003..03f2dc2470b5 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1468,16 +1468,39 @@ static int fb_check_foreignness(struct fb_info *fi) return 0; } -static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw) +static bool apertures_overlap(struct aperture *gen, struct aperture *hw) { /* is the generic aperture base the same as the HW one */ - if (gen->aperture_base == hw->aperture_base) + if (gen->base == hw->base) return true; /* is the generic aperture base inside the hw base->hw base+size */ - if (gen->aperture_base > hw->aperture_base && gen->aperture_base <= hw->aperture_base + hw->aperture_size) + if (gen->base > hw->base && gen->base <= hw->base + hw->size) return true; return false; } + +static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw) +{ + int i, j; + struct apertures_struct *hwa = hw->apertures; + struct apertures_struct *gena = gen->apertures; + if (!hwa || !gena) + return false; + + for (i = 0; i < hwa->count; ++i) { + struct aperture *h = &hwa->ranges[i]; + for (j = 0; j < gena->count; ++j) { + struct aperture *g = &gena->ranges[j]; + printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n", + g->base, g->size, h->base, h->size); + if (apertures_overlap(g, h)) + return true; + } + } + + return false; +} + /** * register_framebuffer - registers a frame buffer device * @fb_info: frame buffer info structure diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 81aa3129c17d..0a08f1341227 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -80,6 +80,7 @@ EXPORT_SYMBOL(framebuffer_alloc); */ void framebuffer_release(struct fb_info *info) { + kfree(info->apertures); kfree(info); } EXPORT_SYMBOL(framebuffer_release); diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 61f8b8f919b0..46dda7d8aaee 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -285,7 +285,7 @@ static void offb_destroy(struct fb_info *info) { if (info->screen_base) iounmap(info->screen_base); - release_mem_region(info->aperture_base, info->aperture_size); + release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); framebuffer_release(info); } @@ -491,8 +491,11 @@ static void __init offb_init_fb(const char *name, const char *full_name, var->vmode = FB_VMODE_NONINTERLACED; /* set offb aperture size for generic probing */ - info->aperture_base = address; - info->aperture_size = fix->smem_len; + info->apertures = alloc_apertures(1); + if (!info->apertures) + goto out_aper; + info->apertures->ranges[0].base = address; + info->apertures->ranges[0].size = fix->smem_len; info->fbops = &offb_ops; info->screen_base = ioremap(address, fix->smem_len); @@ -501,17 +504,20 @@ static void __init offb_init_fb(const char *name, const char *full_name, fb_alloc_cmap(&info->cmap, 256, 0); - if (register_framebuffer(info) < 0) { - iounmap(par->cmap_adr); - par->cmap_adr = NULL; - iounmap(info->screen_base); - framebuffer_release(info); - release_mem_region(res_start, res_size); - return; - } + if (register_framebuffer(info) < 0) + goto out_err; printk(KERN_INFO "fb%d: Open Firmware frame buffer device on %s\n", info->node, full_name); + return; + +out_err: + iounmap(info->screen_base); +out_aper: + iounmap(par->cmap_adr); + par->cmap_adr = NULL; + framebuffer_release(info); + release_mem_region(res_start, res_size); } diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 0cadf7aee27e..090aa1a9be6e 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -177,7 +177,7 @@ static void vesafb_destroy(struct fb_info *info) { if (info->screen_base) iounmap(info->screen_base); - release_mem_region(info->aperture_base, info->aperture_size); + release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); framebuffer_release(info); } @@ -295,8 +295,13 @@ static int __init vesafb_probe(struct platform_device *dev) info->par = NULL; /* set vesafb aperture size for generic probing */ - info->aperture_base = screen_info.lfb_base; - info->aperture_size = size_total; + info->apertures = alloc_apertures(1); + if (!info->apertures) { + err = -ENOMEM; + goto err; + } + info->apertures->ranges[0].base = screen_info.lfb_base; + info->apertures->ranges[0].size = size_total; info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len); if (!info->screen_base) { diff --git a/include/linux/fb.h b/include/linux/fb.h index c10163b4c40e..de5ff5fa8380 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -403,6 +403,7 @@ struct fb_cursor { #include #include #include +#include #include struct vm_area_struct; @@ -862,10 +863,22 @@ struct fb_info { /* we need the PCI or similiar aperture base/size not smem_start/size as smem_start may just be an object allocated inside the aperture so may not actually overlap */ - resource_size_t aperture_base; - resource_size_t aperture_size; + struct apertures_struct { + unsigned int count; + struct aperture { + resource_size_t base; + resource_size_t size; + } ranges[0]; + } *apertures; }; +static inline struct apertures_struct *alloc_apertures(unsigned int max_num) { + struct apertures_struct *a = kzalloc(sizeof(struct apertures_struct) + + max_num * sizeof(struct aperture), GFP_KERNEL); + a->count = max_num; + return a; +} + #ifdef MODULE #define FBINFO_DEFAULT FBINFO_MODULE #else -- cgit v1.2.3 From 06415c564fb98562a4d6b6215615deb2d1cc0dae Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sun, 16 May 2010 17:29:56 +0200 Subject: fbmem, drm/nouveau: kick firmware framebuffers as soon as possible Currently vesafb/efifb/... is kicked when hardware driver is registering framebuffer. To do it hardware must be fully functional, so there's a short window between start of initialisation and framebuffer registration when two drivers touch the hardware. Unfortunately sometimes it breaks nouveau initialisation. Fix it by kicking firmware driver(s) before we start touching the hardware. Reported-by: Didier Spaier Tested-by: Didier Spaier Signed-off-by: Marcin Slusarz Cc: Ben Skeggs Cc: Peter Jones Cc: Andrew Morton Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + drivers/gpu/drm/nouveau/nouveau_fbcon.c | 19 +-------------- drivers/gpu/drm/nouveau/nouveau_state.c | 43 +++++++++++++++++++++++++++++++++ drivers/video/fbmem.c | 43 +++++++++++++++++++-------------- include/linux/fb.h | 1 + 5 files changed, 71 insertions(+), 36 deletions(-) (limited to 'drivers/video') diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 5b47b79f45e8..94d8dd27bde8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -624,6 +624,7 @@ struct drm_nouveau_private { } debugfs; struct nouveau_fbdev *nfbdev; + struct apertures_struct *apertures; }; static inline struct drm_nouveau_private * diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 292c7ff95105..2c2199329cc1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -183,7 +183,6 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, struct drm_mode_fb_cmd mode_cmd; struct pci_dev *pdev = dev->pdev; struct device *device = &pdev->dev; - struct apertures_struct *aper; int size, ret; mode_cmd.width = sizes->surface_width; @@ -267,28 +266,12 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, info->fix.mmio_len = pci_resource_len(pdev, 1); /* Set aperture base/size for vesafb takeover */ - aper = info->apertures = alloc_apertures(3); + info->apertures = dev_priv->apertures; if (!info->apertures) { ret = -ENOMEM; goto out_unref; } - aper->ranges[0].base = pci_resource_start(pdev, 1); - aper->ranges[0].size = pci_resource_len(pdev, 1); - aper->count = 1; - - if (pci_resource_len(pdev, 2)) { - aper->ranges[aper->count].base = pci_resource_start(pdev, 2); - aper->ranges[aper->count].size = pci_resource_len(pdev, 2); - aper->count++; - } - - if (pci_resource_len(pdev, 3)) { - aper->ranges[aper->count].base = pci_resource_start(pdev, 3); - aper->ranges[aper->count].size = pci_resource_len(pdev, 3); - aper->count++; - } - info->pixmap.size = 64*1024; info->pixmap.buf_align = 8; info->pixmap.access_align = 32; diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 92100a9678ba..75c5c465e08e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -639,6 +639,43 @@ static void nouveau_OF_copy_vbios_to_ramin(struct drm_device *dev) #endif } +static struct apertures_struct *nouveau_get_apertures(struct drm_device *dev) +{ + struct pci_dev *pdev = dev->pdev; + struct apertures_struct *aper = alloc_apertures(3); + if (!aper) + return NULL; + + aper->ranges[0].base = pci_resource_start(pdev, 1); + aper->ranges[0].size = pci_resource_len(pdev, 1); + aper->count = 1; + + if (pci_resource_len(pdev, 2)) { + aper->ranges[aper->count].base = pci_resource_start(pdev, 2); + aper->ranges[aper->count].size = pci_resource_len(pdev, 2); + aper->count++; + } + + if (pci_resource_len(pdev, 3)) { + aper->ranges[aper->count].base = pci_resource_start(pdev, 3); + aper->ranges[aper->count].size = pci_resource_len(pdev, 3); + aper->count++; + } + + return aper; +} + +static int nouveau_remove_conflicting_drivers(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + dev_priv->apertures = nouveau_get_apertures(dev); + if (!dev_priv->apertures) + return -ENOMEM; + + remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb"); + return 0; +} + int nouveau_load(struct drm_device *dev, unsigned long flags) { struct drm_nouveau_private *dev_priv; @@ -726,6 +763,12 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", dev_priv->card_type, reg0); + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + int ret = nouveau_remove_conflicting_drivers(dev); + if (ret) + return ret; + } + /* map larger RAMIN aperture on NV40 cards */ dev_priv->ramin = NULL; if (dev_priv->card_type >= NV_40) { diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 03f2dc2470b5..7cfcd716fd5f 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1479,11 +1479,10 @@ static bool apertures_overlap(struct aperture *gen, struct aperture *hw) return false; } -static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw) +static bool fb_do_apertures_overlap(struct apertures_struct *gena, + struct apertures_struct *hwa) { int i, j; - struct apertures_struct *hwa = hw->apertures; - struct apertures_struct *gena = gen->apertures; if (!hwa || !gena) return false; @@ -1501,6 +1500,28 @@ static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw) return false; } +void remove_conflicting_framebuffers(struct apertures_struct *a, const char *name) +{ + int i; + + /* check all firmware fbs and kick off if the base addr overlaps */ + for (i = 0 ; i < FB_MAX; i++) { + if (!registered_fb[i]) + continue; + + if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE)) + continue; + + if (fb_do_apertures_overlap(registered_fb[i]->apertures, a)) { + printk(KERN_ERR "fb: conflicting fb hw usage " + "%s vs %s - removing generic driver\n", + name, registered_fb[i]->fix.id); + unregister_framebuffer(registered_fb[i]); + } + } +} +EXPORT_SYMBOL(remove_conflicting_framebuffers); + /** * register_framebuffer - registers a frame buffer device * @fb_info: frame buffer info structure @@ -1524,21 +1545,7 @@ register_framebuffer(struct fb_info *fb_info) if (fb_check_foreignness(fb_info)) return -ENOSYS; - /* check all firmware fbs and kick off if the base addr overlaps */ - for (i = 0 ; i < FB_MAX; i++) { - if (!registered_fb[i]) - continue; - - if (registered_fb[i]->flags & FBINFO_MISC_FIRMWARE) { - if (fb_do_apertures_overlap(registered_fb[i], fb_info)) { - printk(KERN_ERR "fb: conflicting fb hw usage " - "%s vs %s - removing generic driver\n", - fb_info->fix.id, - registered_fb[i]->fix.id); - unregister_framebuffer(registered_fb[i]); - } - } - } + remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id); num_registered_fb++; for (i = 0 ; i < FB_MAX; i++) diff --git a/include/linux/fb.h b/include/linux/fb.h index de5ff5fa8380..f88e2549123d 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -971,6 +971,7 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, /* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); extern int unregister_framebuffer(struct fb_info *fb_info); +extern void remove_conflicting_framebuffers(struct apertures_struct *a, const char *name); extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); extern int fb_show_logo(struct fb_info *fb_info, int rotate); extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); -- cgit v1.2.3 From 3b9676e7ac6eff4f50f1b48b6c36664f55b79507 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Sun, 16 May 2010 17:33:09 +0200 Subject: vga16fb, drm: vga16fb->drm handoff let vga16fb claim 0xA0000+0x10000 region as its aperture; drm drivers don't use it, so we have to detect it and kick vga16fb manually - but only if drm is driving the primary card Signed-off-by: Marcin Slusarz Cc: James Simmons Cc: Dave Airlie Cc: Ben Skeggs Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_state.c | 7 ++++++- drivers/video/fbmem.c | 14 +++++++++++--- drivers/video/vga16fb.c | 26 +++++++++++++++++++------- include/linux/fb.h | 3 ++- 4 files changed, 38 insertions(+), 12 deletions(-) (limited to 'drivers/video') diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 75c5c465e08e..c667a1138c33 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -668,11 +668,16 @@ static struct apertures_struct *nouveau_get_apertures(struct drm_device *dev) static int nouveau_remove_conflicting_drivers(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + bool primary = false; dev_priv->apertures = nouveau_get_apertures(dev); if (!dev_priv->apertures) return -ENOMEM; - remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb"); +#ifdef CONFIG_X86 + primary = dev->pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; +#endif + + remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb", primary); return 0; } diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 7cfcd716fd5f..e08b7b5cb326 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1500,19 +1500,26 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena, return false; } -void remove_conflicting_framebuffers(struct apertures_struct *a, const char *name) +#define VGA_FB_PHYS 0xA0000 +void remove_conflicting_framebuffers(struct apertures_struct *a, + const char *name, bool primary) { int i; /* check all firmware fbs and kick off if the base addr overlaps */ for (i = 0 ; i < FB_MAX; i++) { + struct apertures_struct *gen_aper; if (!registered_fb[i]) continue; if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE)) continue; - if (fb_do_apertures_overlap(registered_fb[i]->apertures, a)) { + gen_aper = registered_fb[i]->apertures; + if (fb_do_apertures_overlap(gen_aper, a) || + (primary && gen_aper && gen_aper->count && + gen_aper->ranges[0].base == VGA_FB_PHYS)) { + printk(KERN_ERR "fb: conflicting fb hw usage " "%s vs %s - removing generic driver\n", name, registered_fb[i]->fix.id); @@ -1545,7 +1552,8 @@ register_framebuffer(struct fb_info *fb_info) if (fb_check_foreignness(fb_info)) return -ENOSYS; - remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id); + remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, + fb_is_primary_device(fb_info)); num_registered_fb++; for (i = 0 ; i < FB_MAX; i++) diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index bf638a47a5b3..149c47ac7e93 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -1263,10 +1263,19 @@ static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image vga_imageblit_color(info, image); } +static void vga16fb_destroy(struct fb_info *info) +{ + iounmap(info->screen_base); + fb_dealloc_cmap(&info->cmap); + /* XXX unshare VGA regions */ + framebuffer_release(info); +} + static struct fb_ops vga16fb_ops = { .owner = THIS_MODULE, .fb_open = vga16fb_open, .fb_release = vga16fb_release, + .fb_destroy = vga16fb_destroy, .fb_check_var = vga16fb_check_var, .fb_set_par = vga16fb_set_par, .fb_setcolreg = vga16fb_setcolreg, @@ -1306,6 +1315,11 @@ static int __devinit vga16fb_probe(struct platform_device *dev) ret = -ENOMEM; goto err_fb_alloc; } + info->apertures = alloc_apertures(1); + if (!info->apertures) { + ret = -ENOMEM; + goto err_ioremap; + } /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0); @@ -1335,7 +1349,7 @@ static int __devinit vga16fb_probe(struct platform_device *dev) info->fix = vga16fb_fix; /* supports rectangles with widths of multiples of 8 */ info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31; - info->flags = FBINFO_FLAG_DEFAULT | + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE | FBINFO_HWACCEL_YPAN; i = (info->var.bits_per_pixel == 8) ? 256 : 16; @@ -1354,6 +1368,9 @@ static int __devinit vga16fb_probe(struct platform_device *dev) vga16fb_update_fix(info); + info->apertures->ranges[0].base = VGA_FB_PHYS; + info->apertures->ranges[0].size = VGA_FB_PHYS_LEN; + if (register_framebuffer(info) < 0) { printk(KERN_ERR "vga16fb: unable to register framebuffer\n"); ret = -EINVAL; @@ -1380,13 +1397,8 @@ static int vga16fb_remove(struct platform_device *dev) { struct fb_info *info = platform_get_drvdata(dev); - if (info) { + if (info) unregister_framebuffer(info); - iounmap(info->screen_base); - fb_dealloc_cmap(&info->cmap); - /* XXX unshare VGA regions */ - framebuffer_release(info); - } return 0; } diff --git a/include/linux/fb.h b/include/linux/fb.h index f88e2549123d..1296af45169d 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -971,7 +971,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, /* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); extern int unregister_framebuffer(struct fb_info *fb_info); -extern void remove_conflicting_framebuffers(struct apertures_struct *a, const char *name); +extern void remove_conflicting_framebuffers(struct apertures_struct *a, + const char *name, bool primary); extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); extern int fb_show_logo(struct fb_info *fb_info, int rotate); extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); -- cgit v1.2.3 From b4d78bf7a4663c8354ec9432eb9631b144a33ffa Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 17 Mar 2010 13:35:19 +0100 Subject: OMAP: DSS2: Add Kconfig option for DPI display type This allows us to disable DPI on systems that do not have it Signed-off-by: Roger Quadros Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/Kconfig | 6 ++++++ drivers/video/omap2/dss/Makefile | 3 ++- drivers/video/omap2/dss/core.c | 4 ++++ drivers/video/omap2/dss/display.c | 4 ++++ 4 files changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 87afb81b2c44..43b64403eaa4 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -36,6 +36,12 @@ config OMAP2_DSS_COLLECT_IRQ_STATS /omapdss/dispc_irq for DISPC interrupts, and /omapdss/dsi_irq for DSI interrupts. +config OMAP2_DSS_DPI + bool "DPI support" + default y + help + DPI Interface. This is the Parallel Display Interface. + config OMAP2_DSS_RFBI bool "RFBI support" default n diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index 980c72c2db98..d71b5d9d71b1 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_OMAP2_DSS) += omapdss.o -omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o +omapdss-y := core.o dss.o dispc.o display.o manager.o overlay.o +omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 7ebe50b335ed..6d54467e5e20 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -526,11 +526,13 @@ static int omap_dss_probe(struct platform_device *pdev) } #endif +#ifdef CONFIG_OMAP2_DSS_DPI r = dpi_init(pdev); if (r) { DSSERR("Failed to initialize dpi\n"); goto fail0; } +#endif r = dispc_init(); if (r) { @@ -601,7 +603,9 @@ static int omap_dss_remove(struct platform_device *pdev) venc_exit(); #endif dispc_exit(); +#ifdef CONFIG_OMAP2_DSS_DPI dpi_exit(); +#endif #ifdef CONFIG_OMAP2_DSS_RFBI rfbi_exit(); #endif diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 6a74ea116d29..71389630b108 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -392,7 +392,9 @@ void dss_init_device(struct platform_device *pdev, int r; switch (dssdev->type) { +#ifdef CONFIG_OMAP2_DSS_DPI case OMAP_DISPLAY_TYPE_DPI: +#endif #ifdef CONFIG_OMAP2_DSS_RFBI case OMAP_DISPLAY_TYPE_DBI: #endif @@ -413,9 +415,11 @@ void dss_init_device(struct platform_device *pdev, } switch (dssdev->type) { +#ifdef CONFIG_OMAP2_DSS_DPI case OMAP_DISPLAY_TYPE_DPI: r = dpi_init_display(dssdev); break; +#endif #ifdef CONFIG_OMAP2_DSS_RFBI case OMAP_DISPLAY_TYPE_DBI: r = rfbi_init_display(dssdev); -- cgit v1.2.3 From b1d145b6d3c07cb9ccb6afb224c78a9d61f8cd17 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 17 Mar 2010 13:35:20 +0100 Subject: OMAP: DSS2: Remove redundant enable/disable calls from SDI Panel enable/disable is now done via the panel driver, so we should not call the panel driver again Signed-off-by: Roger Quadros Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/sdi.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 12eb4042dd82..3de3c1e559aa 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -115,17 +115,9 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) dssdev->manager->enable(dssdev->manager); - if (dssdev->driver->enable) { - r = dssdev->driver->enable(dssdev); - if (r) - goto err3; - } - sdi.skip_init = 0; return 0; -err3: - dssdev->manager->disable(dssdev->manager); err2: dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); err1: @@ -137,9 +129,6 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable); void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) { - if (dssdev->driver->disable) - dssdev->driver->disable(dssdev); - dssdev->manager->disable(dssdev->manager); dss_sdi_disable(); -- cgit v1.2.3 From 508886cf98c81cee73cd75943b3d0039801327ab Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 17 Mar 2010 13:35:21 +0100 Subject: OMAP: DSS2: Use vdds_sdi regulator supply in SDI This patch enables the use of vdds_sdi regulator in SDI subsystem. We can disable the vdds_sdi voltage when not in use to save power. Signed-off-by: Roger Quadros Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/sdi.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 3de3c1e559aa..ee07a3cc22ef 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -23,13 +23,16 @@ #include #include #include +#include #include +#include #include "dss.h" static struct { bool skip_init; bool update_enabled; + struct regulator *vdds_sdi_reg; } sdi; static void sdi_basic_init(void) @@ -57,6 +60,10 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) goto err0; } + r = regulator_enable(sdi.vdds_sdi_reg); + if (r) + goto err1; + /* In case of skip_init sdi_init has already enabled the clocks */ if (!sdi.skip_init) dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); @@ -120,6 +127,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) return 0; err2: dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + regulator_disable(sdi.vdds_sdi_reg); err1: omap_dss_stop_device(dssdev); err0: @@ -135,6 +143,8 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); + regulator_disable(sdi.vdds_sdi_reg); + omap_dss_stop_device(dssdev); } EXPORT_SYMBOL(omapdss_sdi_display_disable); @@ -151,6 +161,11 @@ int sdi_init(bool skip_init) /* we store this for first display enable, then clear it */ sdi.skip_init = skip_init; + sdi.vdds_sdi_reg = dss_get_vdds_sdi(); + if (IS_ERR(sdi.vdds_sdi_reg)) { + DSSERR("can't get VDDS_SDI regulator\n"); + return PTR_ERR(sdi.vdds_sdi_reg); + } /* * Enable clocks already here, otherwise there would be a toggle * of them until sdi_display_enable is called. -- cgit v1.2.3 From 238a41329ca208d1170962260babb428b6e222c2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 18 Mar 2010 10:32:05 +0100 Subject: OMAP: DSS2: fix lock_fb_info() and omapfb_lock() locking order Framebuffer ioctl processing forces lock_fb_info() -> omapfb_lock() locking order. Follow that order to avoid possible circular locking dependency, detected by lockdep. Signed-off-by: Jani Nikula Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/omapfb/omapfb-ioctl.c | 4 ++-- drivers/video/omap2/omapfb/omapfb-sysfs.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 1ffa760b8545..2c0f01c44aab 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -183,13 +183,13 @@ int omapfb_update_window(struct fb_info *fbi, struct omapfb2_device *fbdev = ofbi->fbdev; int r; - omapfb_lock(fbdev); lock_fb_info(fbi); + omapfb_lock(fbdev); r = omapfb_update_window_nolock(fbi, x, y, w, h); - unlock_fb_info(fbi); omapfb_unlock(fbdev); + unlock_fb_info(fbi); return r; } diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index 62bb88f5c192..e10445017985 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c @@ -137,8 +137,8 @@ static ssize_t show_overlays(struct device *dev, ssize_t l = 0; int t; - omapfb_lock(fbdev); lock_fb_info(fbi); + omapfb_lock(fbdev); for (t = 0; t < ofbi->num_overlays; t++) { struct omap_overlay *ovl = ofbi->overlays[t]; @@ -154,8 +154,8 @@ static ssize_t show_overlays(struct device *dev, l += snprintf(buf + l, PAGE_SIZE - l, "\n"); - unlock_fb_info(fbi); omapfb_unlock(fbdev); + unlock_fb_info(fbi); return l; } @@ -195,8 +195,8 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, if (buf[len - 1] == '\n') len = len - 1; - omapfb_lock(fbdev); lock_fb_info(fbi); + omapfb_lock(fbdev); if (len > 0) { char *p = (char *)buf; @@ -303,8 +303,8 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, r = count; out: - unlock_fb_info(fbi); omapfb_unlock(fbdev); + unlock_fb_info(fbi); return r; } -- cgit v1.2.3 From 27b67c92a30967e3a9e9ea082d4ca4bc6882f879 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 18 Mar 2010 10:32:06 +0100 Subject: OMAP: DSS2: check lock_fb_info() return value Give up if lock_fb_info() fails, following the same convention as other lock_fb_info() users. Signed-off-by: Jani Nikula Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/omapfb/omapfb-ioctl.c | 3 ++- drivers/video/omap2/omapfb/omapfb-sysfs.c | 21 ++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 2c0f01c44aab..9c7361871d78 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -183,7 +183,8 @@ int omapfb_update_window(struct fb_info *fbi, struct omapfb2_device *fbdev = ofbi->fbdev; int r; - lock_fb_info(fbi); + if (!lock_fb_info(fbi)) + return -ENODEV; omapfb_lock(fbdev); r = omapfb_update_window_nolock(fbi, x, y, w, h); diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index e10445017985..5179219128bd 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c @@ -57,7 +57,8 @@ static ssize_t store_rotate_type(struct device *dev, if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) return -EINVAL; - lock_fb_info(fbi); + if (!lock_fb_info(fbi)) + return -ENODEV; r = 0; if (rot_type == ofbi->rotation_type) @@ -105,7 +106,8 @@ static ssize_t store_mirror(struct device *dev, if (mirror != 0 && mirror != 1) return -EINVAL; - lock_fb_info(fbi); + if (!lock_fb_info(fbi)) + return -ENODEV; ofbi->mirror = mirror; @@ -137,7 +139,8 @@ static ssize_t show_overlays(struct device *dev, ssize_t l = 0; int t; - lock_fb_info(fbi); + if (!lock_fb_info(fbi)) + return -ENODEV; omapfb_lock(fbdev); for (t = 0; t < ofbi->num_overlays; t++) { @@ -195,7 +198,8 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr, if (buf[len - 1] == '\n') len = len - 1; - lock_fb_info(fbi); + if (!lock_fb_info(fbi)) + return -ENODEV; omapfb_lock(fbdev); if (len > 0) { @@ -317,7 +321,8 @@ static ssize_t show_overlays_rotate(struct device *dev, ssize_t l = 0; int t; - lock_fb_info(fbi); + if (!lock_fb_info(fbi)) + return -ENODEV; for (t = 0; t < ofbi->num_overlays; t++) { l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", @@ -345,7 +350,8 @@ static ssize_t store_overlays_rotate(struct device *dev, if (buf[len - 1] == '\n') len = len - 1; - lock_fb_info(fbi); + if (!lock_fb_info(fbi)) + return -ENODEV; if (len > 0) { char *p = (char *)buf; @@ -416,7 +422,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr, size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0)); - lock_fb_info(fbi); + if (!lock_fb_info(fbi)) + return -ENODEV; for (i = 0; i < ofbi->num_overlays; i++) { if (ofbi->overlays[i]->info.enabled) { -- cgit v1.2.3 From 35bc42c50432d3dde0119f7630f1e4574bd67519 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 24 Mar 2010 11:59:37 +0100 Subject: OMAP: DSS2: VENC: don't call platform_enable/disable() twice platform_enable/disable() is already called in venc_power_on/off(), so don't do it again in venc_panel_enable/disable(). Signed-off-by: Jani Nikula Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/venc.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index f0ba5732d84a..eff35050e28a 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -479,12 +479,6 @@ static int venc_panel_enable(struct omap_dss_device *dssdev) goto err1; } - if (dssdev->platform_enable) { - r = dssdev->platform_enable(dssdev); - if (r) - goto err2; - } - venc_power_on(dssdev); venc.wss_data = 0; @@ -494,13 +488,9 @@ static int venc_panel_enable(struct omap_dss_device *dssdev) /* wait couple of vsyncs until enabling the LCD */ msleep(50); - mutex_unlock(&venc.venc_lock); - - return r; -err2: - venc_power_off(dssdev); err1: mutex_unlock(&venc.venc_lock); + return r; } @@ -524,9 +514,6 @@ static void venc_panel_disable(struct omap_dss_device *dssdev) /* wait at least 5 vsyncs after disabling the LCD */ msleep(100); - if (dssdev->platform_disable) - dssdev->platform_disable(dssdev); - dssdev->state = OMAP_DSS_DISPLAY_DISABLED; end: mutex_unlock(&venc.venc_lock); -- cgit v1.2.3 From 279fcd48c4a426050422b2d196fd99c2b5ae7d71 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 24 Mar 2010 11:59:38 +0100 Subject: OMAP: DSS2: Fix device disable when driver is not loaded Only call driver disable when device isn't already disabled, which also handles the driver not loaded case. Signed-off-by: Jani Nikula Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/display.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 71389630b108..ef8c8529dda2 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c @@ -545,7 +545,10 @@ int dss_resume_all_devices(void) static int dss_disable_device(struct device *dev, void *data) { struct omap_dss_device *dssdev = to_dss_device(dev); - dssdev->driver->disable(dssdev); + + if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) + dssdev->driver->disable(dssdev); + return 0; } -- cgit v1.2.3 From f49a951f8a2dacbbb145b6199297fcc3e493b90f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 26 Mar 2010 16:26:37 +0200 Subject: OMAP: DSS2: Make partial update width even MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are some strange problems with DSI and updates with odd widths. One particular problem is that HS TX timeout triggers easily with updates with odd widths. This patch makes the updates widths even, circumventing the problem. There should be no ill side effects with increasing the update area slightly to make the width even. Signed-off-by: Ville Syrjälä Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/manager.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 0820986d4a68..32ec2ff2e9cf 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -940,6 +940,22 @@ static int configure_dispc(void) return r; } +/* Make the coordinates even. There are some strange problems with OMAP and + * partial DSI update when the update widths are odd. */ +static void make_even(u16 *x, u16 *w) +{ + u16 x1, x2; + + x1 = *x; + x2 = *x + *w; + + x1 &= ~1; + x2 = ALIGN(x2, 2); + + *x = x1; + *w = x2 - x1; +} + /* Configure dispc for partial update. Return possibly modified update * area */ void dss_setup_partial_planes(struct omap_dss_device *dssdev, @@ -968,6 +984,8 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev, return; } + make_even(&x, &w); + spin_lock_irqsave(&dss_cache.lock, flags); /* We need to show the whole overlay if it is scaled. So look for @@ -1029,6 +1047,8 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev, w = x2 - x1; h = y2 - y1; + make_even(&x, &w); + DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n", i, x, y, w, h); } -- cgit v1.2.3 From a3201a0eaed38dd7ece72393a778b4408ec79627 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 3 Mar 2010 14:31:45 +0200 Subject: OMAP: DSS2: Taal: add mutex to protect panel data Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/panel-taal.c | 140 +++++++++++++++++++++++++----- 1 file changed, 119 insertions(+), 21 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 4f3988a41082..1799096a1388 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -67,6 +68,8 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); struct taal_data { + struct mutex lock; + struct backlight_device *bldev; unsigned long hw_guard_end; /* next value of jiffies when we can @@ -510,6 +513,8 @@ static int taal_probe(struct omap_dss_device *dssdev) } td->dssdev = dssdev; + mutex_init(&td->lock); + td->esd_wq = create_singlethread_workqueue("taal_esd"); if (td->esd_wq == NULL) { dev_err(&dssdev->dev, "can't create ESD workqueue\n"); @@ -733,54 +738,96 @@ static void taal_power_off(struct omap_dss_device *dssdev) static int taal_enable(struct omap_dss_device *dssdev) { + struct taal_data *td = dev_get_drvdata(&dssdev->dev); int r; + dev_dbg(&dssdev->dev, "enable\n"); - if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) - return -EINVAL; + mutex_lock(&td->lock); + + if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { + r = -EINVAL; + goto err; + } r = taal_power_on(dssdev); if (r) - return r; + goto err; dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + mutex_unlock(&td->lock); + + return 0; +err: + dev_dbg(&dssdev->dev, "enable failed\n"); + mutex_unlock(&td->lock); return r; } static void taal_disable(struct omap_dss_device *dssdev) { + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + dev_dbg(&dssdev->dev, "disable\n"); + mutex_lock(&td->lock); + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) taal_power_off(dssdev); dssdev->state = OMAP_DSS_DISPLAY_DISABLED; + + mutex_unlock(&td->lock); } static int taal_suspend(struct omap_dss_device *dssdev) { + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + int r; + dev_dbg(&dssdev->dev, "suspend\n"); - if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) - return -EINVAL; + mutex_lock(&td->lock); + + if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { + r = -EINVAL; + goto err; + } taal_power_off(dssdev); dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; + mutex_unlock(&td->lock); + return 0; +err: + mutex_unlock(&td->lock); + return r; } static int taal_resume(struct omap_dss_device *dssdev) { + struct taal_data *td = dev_get_drvdata(&dssdev->dev); int r; + dev_dbg(&dssdev->dev, "resume\n"); - if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) - return -EINVAL; + mutex_lock(&td->lock); + + if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { + r = -EINVAL; + goto err; + } r = taal_power_on(dssdev); dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + + mutex_unlock(&td->lock); + + return r; +err: + mutex_unlock(&td->lock); return r; } @@ -799,6 +846,7 @@ static int taal_update(struct omap_dss_device *dssdev, dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); + mutex_lock(&td->lock); dsi_bus_lock(); if (!td->enabled) { @@ -820,18 +868,24 @@ static int taal_update(struct omap_dss_device *dssdev, goto err; /* note: no bus_unlock here. unlock is in framedone_cb */ + mutex_unlock(&td->lock); return 0; err: dsi_bus_unlock(); + mutex_unlock(&td->lock); return r; } static int taal_sync(struct omap_dss_device *dssdev) { + struct taal_data *td = dev_get_drvdata(&dssdev->dev); + dev_dbg(&dssdev->dev, "sync\n"); + mutex_lock(&td->lock); dsi_bus_lock(); dsi_bus_unlock(); + mutex_unlock(&td->lock); dev_dbg(&dssdev->dev, "sync done\n"); @@ -861,13 +915,16 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) { + struct taal_data *td = dev_get_drvdata(&dssdev->dev); int r; + mutex_lock(&td->lock); dsi_bus_lock(); r = _taal_enable_te(dssdev, enable); dsi_bus_unlock(); + mutex_unlock(&td->lock); return r; } @@ -875,7 +932,13 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) static int taal_get_te(struct omap_dss_device *dssdev) { struct taal_data *td = dev_get_drvdata(&dssdev->dev); - return td->te_enabled; + int r; + + mutex_lock(&td->lock); + r = td->te_enabled; + mutex_unlock(&td->lock); + + return r; } static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) @@ -885,6 +948,7 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) dev_dbg(&dssdev->dev, "rotate %d\n", rotate); + mutex_lock(&td->lock); dsi_bus_lock(); if (td->enabled) { @@ -896,16 +960,24 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) td->rotate = rotate; dsi_bus_unlock(); + mutex_unlock(&td->lock); return 0; err: dsi_bus_unlock(); + mutex_unlock(&td->lock); return r; } static u8 taal_get_rotate(struct omap_dss_device *dssdev) { struct taal_data *td = dev_get_drvdata(&dssdev->dev); - return td->rotate; + int r; + + mutex_lock(&td->lock); + r = td->rotate; + mutex_unlock(&td->lock); + + return r; } static int taal_mirror(struct omap_dss_device *dssdev, bool enable) @@ -915,6 +987,7 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable) dev_dbg(&dssdev->dev, "mirror %d\n", enable); + mutex_lock(&td->lock); dsi_bus_lock(); if (td->enabled) { r = taal_set_addr_mode(td->rotate, enable); @@ -925,23 +998,33 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable) td->mirror = enable; dsi_bus_unlock(); + mutex_unlock(&td->lock); return 0; err: dsi_bus_unlock(); + mutex_unlock(&td->lock); return r; } static bool taal_get_mirror(struct omap_dss_device *dssdev) { struct taal_data *td = dev_get_drvdata(&dssdev->dev); - return td->mirror; + int r; + + mutex_lock(&td->lock); + r = td->mirror; + mutex_unlock(&td->lock); + + return r; } static int taal_run_test(struct omap_dss_device *dssdev, int test_num) { + struct taal_data *td = dev_get_drvdata(&dssdev->dev); u8 id1, id2, id3; int r; + mutex_lock(&td->lock); dsi_bus_lock(); r = taal_dcs_read_1(DCS_GET_ID1, &id1); @@ -955,9 +1038,11 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num) goto err; dsi_bus_unlock(); + mutex_unlock(&td->lock); return 0; err: dsi_bus_unlock(); + mutex_unlock(&td->lock); return r; } @@ -971,12 +1056,16 @@ static int taal_memory_read(struct omap_dss_device *dssdev, unsigned buf_used = 0; struct taal_data *td = dev_get_drvdata(&dssdev->dev); - if (!td->enabled) - return -ENODEV; - if (size < w * h * 3) return -ENOMEM; + mutex_lock(&td->lock); + + if (!td->enabled) { + r = -ENODEV; + goto err1; + } + size = min(w * h * 3, dssdev->panel.timings.x_res * dssdev->panel.timings.y_res * 3); @@ -995,7 +1084,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev, r = dsi_vc_set_max_rx_packet_size(TCH, plen); if (r) - goto err0; + goto err2; while (buf_used < size) { u8 dcs_cmd = first ? 0x2e : 0x3e; @@ -1006,7 +1095,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev, if (r < 0) { dev_err(&dssdev->dev, "read error\n"); - goto err; + goto err3; } buf_used += r; @@ -1020,16 +1109,18 @@ static int taal_memory_read(struct omap_dss_device *dssdev, dev_err(&dssdev->dev, "signal pending, " "aborting memory read\n"); r = -ERESTARTSYS; - goto err; + goto err3; } } r = buf_used; -err: +err3: dsi_vc_set_max_rx_packet_size(TCH, 1); -err0: +err2: dsi_bus_unlock(); +err1: + mutex_unlock(&td->lock); return r; } @@ -1041,8 +1132,12 @@ static void taal_esd_work(struct work_struct *work) u8 state1, state2; int r; - if (!td->enabled) + mutex_lock(&td->lock); + + if (!td->enabled) { + mutex_unlock(&td->lock); return; + } dsi_bus_lock(); @@ -1084,16 +1179,19 @@ static void taal_esd_work(struct work_struct *work) queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); + mutex_unlock(&td->lock); return; err: dev_err(&dssdev->dev, "performing LCD reset\n"); - taal_disable(dssdev); - taal_enable(dssdev); + taal_power_off(dssdev); + taal_power_on(dssdev); dsi_bus_unlock(); queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); + + mutex_unlock(&td->lock); } static int taal_set_update_mode(struct omap_dss_device *dssdev, -- cgit v1.2.3 From 6df37271f879f14119a0605549f1a2574e83b4fe Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 10 Mar 2010 18:24:54 +0100 Subject: OMAP: DSS2: Taal: Fix DSI bus locking problem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If omapdss_dsi_display_enable() failed the DSI bus was left locked. Also if the operation failed later omapdss_dsi_display_disable() would get called without holding the bus lock. Signed-off-by: Ville Syrjälä Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/panel-taal.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 1799096a1388..aaf5d308a046 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -702,10 +702,9 @@ static int taal_power_on(struct omap_dss_device *dssdev) return 0; err: - dsi_bus_unlock(); - omapdss_dsi_display_disable(dssdev); err0: + dsi_bus_unlock(); if (dssdev->platform_disable) dssdev->platform_disable(dssdev); -- cgit v1.2.3 From 2b88c5bc310dc7a2bf9341b86e9f01cf05e8769e Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Thu, 15 Apr 2010 16:00:00 +0200 Subject: OMAP: LCD LS037V7DW01: Add Backlight driver support Tested on OMAP3EVM for OMAP3530 and AM/DM 3730. Signed-off-by: Vaibhav Hiremath [tomi.valkeinen@nokia.com: added slab.h include] [tomi.valkeinen@nokia.com: added dependency to BACKLIGHT_CLASS_DEVICE] Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/Kconfig | 1 + .../video/omap2/displays/panel-sharp-ls037v7dw01.c | 78 ++++++++++++++++++++++ 2 files changed, 79 insertions(+) (limited to 'drivers/video') diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index dfb57ee50861..ea8ccd362c22 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig @@ -10,6 +10,7 @@ config PANEL_GENERIC config PANEL_SHARP_LS037V7DW01 tristate "Sharp LS037V7DW01 LCD Panel" depends on OMAP2_DSS + select BACKLIGHT_CLASS_DEVICE help LCD Panel used in TI's SDP3430 and EVM boards diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c index 8d51a5e6341c..7d9eb2b1f5af 100644 --- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c @@ -20,10 +20,17 @@ #include #include #include +#include +#include #include +#include #include +struct sharp_data { + struct backlight_device *bl; +}; + static struct omap_video_timings sharp_ls_timings = { .x_res = 480, .y_res = 640, @@ -39,18 +46,89 @@ static struct omap_video_timings sharp_ls_timings = { .vbp = 1, }; +static int sharp_ls_bl_update_status(struct backlight_device *bl) +{ + struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev); + int level; + + if (!dssdev->set_backlight) + return -EINVAL; + + if (bl->props.fb_blank == FB_BLANK_UNBLANK && + bl->props.power == FB_BLANK_UNBLANK) + level = bl->props.brightness; + else + level = 0; + + return dssdev->set_backlight(dssdev, level); +} + +static int sharp_ls_bl_get_brightness(struct backlight_device *bl) +{ + if (bl->props.fb_blank == FB_BLANK_UNBLANK && + bl->props.power == FB_BLANK_UNBLANK) + return bl->props.brightness; + + return 0; +} + +static const struct backlight_ops sharp_ls_bl_ops = { + .get_brightness = sharp_ls_bl_get_brightness, + .update_status = sharp_ls_bl_update_status, +}; + + + static int sharp_ls_panel_probe(struct omap_dss_device *dssdev) { + struct backlight_properties props; + struct backlight_device *bl; + struct sharp_data *sd; + int r; + dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; dssdev->panel.acb = 0x28; dssdev->panel.timings = sharp_ls_timings; + sd = kzalloc(sizeof(*sd), GFP_KERNEL); + if (!sd) + return -ENOMEM; + + dev_set_drvdata(&dssdev->dev, sd); + + memset(&props, 0, sizeof(struct backlight_properties)); + props.max_brightness = dssdev->max_backlight_level; + + bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev, + &sharp_ls_bl_ops, &props); + if (IS_ERR(bl)) { + r = PTR_ERR(bl); + kfree(sd); + return r; + } + sd->bl = bl; + + bl->props.fb_blank = FB_BLANK_UNBLANK; + bl->props.power = FB_BLANK_UNBLANK; + bl->props.brightness = dssdev->max_backlight_level; + r = sharp_ls_bl_update_status(bl); + if (r < 0) + dev_err(&dssdev->dev, "failed to set lcd brightness\n"); + return 0; } static void sharp_ls_panel_remove(struct omap_dss_device *dssdev) { + struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); + struct backlight_device *bl = sd->bl; + + bl->props.power = FB_BLANK_POWERDOWN; + sharp_ls_bl_update_status(bl); + backlight_device_unregister(bl); + + kfree(sd); } static int sharp_ls_power_on(struct omap_dss_device *dssdev) -- cgit v1.2.3 From a40458eee7ee60a89f89602067921658b87ded73 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Thu, 15 Apr 2010 16:59:03 +0200 Subject: OMAP: DSS2: TPO-TD03MTEA1: fix Kconfig dependency This panel depends on SPI, not I2C. Signed-off-by: Grazvydas Ignotas Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index ea8ccd362c22..4221957b0d2c 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig @@ -34,7 +34,7 @@ config PANEL_TOPPOLY_TDO35S config PANEL_TPO_TD043MTEA1 tristate "TPO TD043MTEA1 LCD Panel" - depends on OMAP2_DSS && I2C + depends on OMAP2_DSS && SPI help LCD Panel used in OMAP3 Pandora -- cgit v1.2.3 From 0188352b2774234575a41864fd0945be42975ee5 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Wed, 10 Mar 2010 17:32:44 +0200 Subject: OMAP: DSS2: Add ACX565AKM Panel Driver This is the panel used on Nokia N900 Signed-off-by: Roger Quadros Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/Kconfig | 6 + drivers/video/omap2/displays/Makefile | 1 + drivers/video/omap2/displays/panel-acx565akm.c | 819 +++++++++++++++++++++++++ 3 files changed, 826 insertions(+) create mode 100644 drivers/video/omap2/displays/panel-acx565akm.c (limited to 'drivers/video') diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index 4221957b0d2c..881c9f77c75a 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig @@ -38,4 +38,10 @@ config PANEL_TPO_TD043MTEA1 help LCD Panel used in OMAP3 Pandora +config PANEL_ACX565AKM + tristate "ACX565AKM Panel" + depends on OMAP2_DSS_SDI + select BACKLIGHT_CLASS_DEVICE + help + This is the LCD panel used on Nokia N900 endmenu diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile index e2bb32168dee..aa386095d7c4 100644 --- a/drivers/video/omap2/displays/Makefile +++ b/drivers/video/omap2/displays/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_PANEL_SHARP_LQ043T1DG01) += panel-sharp-lq043t1dg01.o obj-$(CONFIG_PANEL_TAAL) += panel-taal.o obj-$(CONFIG_PANEL_TOPPOLY_TDO35S) += panel-toppoly-tdo35s.o obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o +obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c new file mode 100644 index 000000000000..1f8eb70e2937 --- /dev/null +++ b/drivers/video/omap2/displays/panel-acx565akm.c @@ -0,0 +1,819 @@ +/* + * Support for ACX565AKM LCD Panel used on Nokia N900 + * + * Copyright (C) 2010 Nokia Corporation + * + * Original Driver Author: Imre Deak + * Based on panel-generic.c by Tomi Valkeinen + * Adapted to new DSS2 framework: Roger Quadros + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MIPID_CMD_READ_DISP_ID 0x04 +#define MIPID_CMD_READ_RED 0x06 +#define MIPID_CMD_READ_GREEN 0x07 +#define MIPID_CMD_READ_BLUE 0x08 +#define MIPID_CMD_READ_DISP_STATUS 0x09 +#define MIPID_CMD_RDDSDR 0x0F +#define MIPID_CMD_SLEEP_IN 0x10 +#define MIPID_CMD_SLEEP_OUT 0x11 +#define MIPID_CMD_DISP_OFF 0x28 +#define MIPID_CMD_DISP_ON 0x29 +#define MIPID_CMD_WRITE_DISP_BRIGHTNESS 0x51 +#define MIPID_CMD_READ_DISP_BRIGHTNESS 0x52 +#define MIPID_CMD_WRITE_CTRL_DISP 0x53 + +#define CTRL_DISP_BRIGHTNESS_CTRL_ON (1 << 5) +#define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4) +#define CTRL_DISP_BACKLIGHT_ON (1 << 2) +#define CTRL_DISP_AUTO_BRIGHTNESS_ON (1 << 1) + +#define MIPID_CMD_READ_CTRL_DISP 0x54 +#define MIPID_CMD_WRITE_CABC 0x55 +#define MIPID_CMD_READ_CABC 0x56 + +#define MIPID_VER_LPH8923 3 +#define MIPID_VER_LS041Y3 4 +#define MIPID_VER_L4F00311 8 +#define MIPID_VER_ACX565AKM 9 + +struct acx565akm_device { + char *name; + int enabled; + int model; + int revision; + u8 display_id[3]; + unsigned has_bc:1; + unsigned has_cabc:1; + unsigned cabc_mode; + unsigned long hw_guard_end; /* next value of jiffies + when we can issue the + next sleep in/out command */ + unsigned long hw_guard_wait; /* max guard time in jiffies */ + + struct spi_device *spi; + struct mutex mutex; + + struct omap_dss_device *dssdev; + struct backlight_device *bl_dev; +}; + +static struct acx565akm_device acx_dev; +static int acx565akm_bl_update_status(struct backlight_device *dev); + +/*--------------------MIPID interface-----------------------------*/ + +static void acx565akm_transfer(struct acx565akm_device *md, int cmd, + const u8 *wbuf, int wlen, u8 *rbuf, int rlen) +{ + struct spi_message m; + struct spi_transfer *x, xfer[5]; + int r; + + BUG_ON(md->spi == NULL); + + spi_message_init(&m); + + memset(xfer, 0, sizeof(xfer)); + x = &xfer[0]; + + cmd &= 0xff; + x->tx_buf = &cmd; + x->bits_per_word = 9; + x->len = 2; + + if (rlen > 1 && wlen == 0) { + /* + * Between the command and the response data there is a + * dummy clock cycle. Add an extra bit after the command + * word to account for this. + */ + x->bits_per_word = 10; + cmd <<= 1; + } + spi_message_add_tail(x, &m); + + if (wlen) { + x++; + x->tx_buf = wbuf; + x->len = wlen; + x->bits_per_word = 9; + spi_message_add_tail(x, &m); + } + + if (rlen) { + x++; + x->rx_buf = rbuf; + x->len = rlen; + spi_message_add_tail(x, &m); + } + + r = spi_sync(md->spi, &m); + if (r < 0) + dev_dbg(&md->spi->dev, "spi_sync %d\n", r); +} + +static inline void acx565akm_cmd(struct acx565akm_device *md, int cmd) +{ + acx565akm_transfer(md, cmd, NULL, 0, NULL, 0); +} + +static inline void acx565akm_write(struct acx565akm_device *md, + int reg, const u8 *buf, int len) +{ + acx565akm_transfer(md, reg, buf, len, NULL, 0); +} + +static inline void acx565akm_read(struct acx565akm_device *md, + int reg, u8 *buf, int len) +{ + acx565akm_transfer(md, reg, NULL, 0, buf, len); +} + +static void hw_guard_start(struct acx565akm_device *md, int guard_msec) +{ + md->hw_guard_wait = msecs_to_jiffies(guard_msec); + md->hw_guard_end = jiffies + md->hw_guard_wait; +} + +static void hw_guard_wait(struct acx565akm_device *md) +{ + unsigned long wait = md->hw_guard_end - jiffies; + + if ((long)wait > 0 && wait <= md->hw_guard_wait) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(wait); + } +} + +/*----------------------MIPID wrappers----------------------------*/ + +static void set_sleep_mode(struct acx565akm_device *md, int on) +{ + int cmd; + + if (on) + cmd = MIPID_CMD_SLEEP_IN; + else + cmd = MIPID_CMD_SLEEP_OUT; + /* + * We have to keep 120msec between sleep in/out commands. + * (8.2.15, 8.2.16). + */ + hw_guard_wait(md); + acx565akm_cmd(md, cmd); + hw_guard_start(md, 120); +} + +static void set_display_state(struct acx565akm_device *md, int enabled) +{ + int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF; + + acx565akm_cmd(md, cmd); +} + +static int panel_enabled(struct acx565akm_device *md) +{ + u32 disp_status; + int enabled; + + acx565akm_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4); + disp_status = __be32_to_cpu(disp_status); + enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10)); + dev_dbg(&md->spi->dev, + "LCD panel %senabled by bootloader (status 0x%04x)\n", + enabled ? "" : "not ", disp_status); + return enabled; +} + +static int panel_detect(struct acx565akm_device *md) +{ + acx565akm_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3); + dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n", + md->display_id[0], md->display_id[1], md->display_id[2]); + + switch (md->display_id[0]) { + case 0x10: + md->model = MIPID_VER_ACX565AKM; + md->name = "acx565akm"; + md->has_bc = 1; + md->has_cabc = 1; + break; + case 0x29: + md->model = MIPID_VER_L4F00311; + md->name = "l4f00311"; + break; + case 0x45: + md->model = MIPID_VER_LPH8923; + md->name = "lph8923"; + break; + case 0x83: + md->model = MIPID_VER_LS041Y3; + md->name = "ls041y3"; + break; + default: + md->name = "unknown"; + dev_err(&md->spi->dev, "invalid display ID\n"); + return -ENODEV; + } + + md->revision = md->display_id[1]; + + dev_info(&md->spi->dev, "omapfb: %s rev %02x LCD detected\n", + md->name, md->revision); + + return 0; +} + +/*----------------------Backlight Control-------------------------*/ + +static void enable_backlight_ctrl(struct acx565akm_device *md, int enable) +{ + u16 ctrl; + + acx565akm_read(md, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1); + if (enable) { + ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON | + CTRL_DISP_BACKLIGHT_ON; + } else { + ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON | + CTRL_DISP_BACKLIGHT_ON); + } + + ctrl |= 1 << 8; + acx565akm_write(md, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2); +} + +static void set_cabc_mode(struct acx565akm_device *md, unsigned mode) +{ + u16 cabc_ctrl; + + md->cabc_mode = mode; + if (!md->enabled) + return; + cabc_ctrl = 0; + acx565akm_read(md, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1); + cabc_ctrl &= ~3; + cabc_ctrl |= (1 << 8) | (mode & 3); + acx565akm_write(md, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2); +} + +static unsigned get_cabc_mode(struct acx565akm_device *md) +{ + return md->cabc_mode; +} + +static unsigned get_hw_cabc_mode(struct acx565akm_device *md) +{ + u8 cabc_ctrl; + + acx565akm_read(md, MIPID_CMD_READ_CABC, &cabc_ctrl, 1); + return cabc_ctrl & 3; +} + +static void acx565akm_set_brightness(struct acx565akm_device *md, int level) +{ + int bv; + + bv = level | (1 << 8); + acx565akm_write(md, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2); + + if (level) + enable_backlight_ctrl(md, 1); + else + enable_backlight_ctrl(md, 0); +} + +static int acx565akm_get_actual_brightness(struct acx565akm_device *md) +{ + u8 bv; + + acx565akm_read(md, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1); + + return bv; +} + + +static int acx565akm_bl_update_status(struct backlight_device *dev) +{ + struct acx565akm_device *md = dev_get_drvdata(&dev->dev); + int r; + int level; + + dev_dbg(&md->spi->dev, "%s\n", __func__); + + mutex_lock(&md->mutex); + + if (dev->props.fb_blank == FB_BLANK_UNBLANK && + dev->props.power == FB_BLANK_UNBLANK) + level = dev->props.brightness; + else + level = 0; + + r = 0; + if (md->has_bc) + acx565akm_set_brightness(md, level); + else if (md->dssdev->set_backlight) + r = md->dssdev->set_backlight(md->dssdev, level); + else + r = -ENODEV; + + mutex_unlock(&md->mutex); + + return r; +} + +static int acx565akm_bl_get_intensity(struct backlight_device *dev) +{ + struct acx565akm_device *md = dev_get_drvdata(&dev->dev); + + dev_dbg(&dev->dev, "%s\n", __func__); + + if (!md->has_bc && md->dssdev->set_backlight == NULL) + return -ENODEV; + + if (dev->props.fb_blank == FB_BLANK_UNBLANK && + dev->props.power == FB_BLANK_UNBLANK) { + if (md->has_bc) + return acx565akm_get_actual_brightness(md); + else + return dev->props.brightness; + } + + return 0; +} + +static const struct backlight_ops acx565akm_bl_ops = { + .get_brightness = acx565akm_bl_get_intensity, + .update_status = acx565akm_bl_update_status, +}; + +/*--------------------Auto Brightness control via Sysfs---------------------*/ + +static const char *cabc_modes[] = { + "off", /* always used when CABC is not supported */ + "ui", + "still-image", + "moving-image", +}; + +static ssize_t show_cabc_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acx565akm_device *md = dev_get_drvdata(dev); + const char *mode_str; + int mode; + int len; + + if (!md->has_cabc) + mode = 0; + else + mode = get_cabc_mode(md); + mode_str = "unknown"; + if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes)) + mode_str = cabc_modes[mode]; + len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str); + + return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1; +} + +static ssize_t store_cabc_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acx565akm_device *md = dev_get_drvdata(dev); + int i; + + for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) { + const char *mode_str = cabc_modes[i]; + int cmp_len = strlen(mode_str); + + if (count > 0 && buf[count - 1] == '\n') + count--; + if (count != cmp_len) + continue; + + if (strncmp(buf, mode_str, cmp_len) == 0) + break; + } + + if (i == ARRAY_SIZE(cabc_modes)) + return -EINVAL; + + if (!md->has_cabc && i != 0) + return -EINVAL; + + mutex_lock(&md->mutex); + set_cabc_mode(md, i); + mutex_unlock(&md->mutex); + + return count; +} + +static ssize_t show_cabc_available_modes(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acx565akm_device *md = dev_get_drvdata(dev); + int len; + int i; + + if (!md->has_cabc) + return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]); + + for (i = 0, len = 0; + len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++) + len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s", + i ? " " : "", cabc_modes[i], + i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : ""); + + return len < PAGE_SIZE ? len : PAGE_SIZE - 1; +} + +static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, + show_cabc_mode, store_cabc_mode); +static DEVICE_ATTR(cabc_available_modes, S_IRUGO, + show_cabc_available_modes, NULL); + +static struct attribute *bldev_attrs[] = { + &dev_attr_cabc_mode.attr, + &dev_attr_cabc_available_modes.attr, + NULL, +}; + +static struct attribute_group bldev_attr_group = { + .attrs = bldev_attrs, +}; + + +/*---------------------------ACX Panel----------------------------*/ + +static int acx_get_recommended_bpp(struct omap_dss_device *dssdev) +{ + return 16; +} + +static struct omap_video_timings acx_panel_timings = { + .x_res = 800, + .y_res = 480, + .pixel_clock = 24000, + .hfp = 28, + .hsw = 4, + .hbp = 24, + .vfp = 3, + .vsw = 3, + .vbp = 4, +}; + +static int acx_panel_probe(struct omap_dss_device *dssdev) +{ + int r; + struct acx565akm_device *md = &acx_dev; + struct backlight_device *bldev; + int max_brightness, brightness; + struct backlight_properties props; + + dev_dbg(&dssdev->dev, "%s\n", __func__); + dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | + OMAP_DSS_LCD_IHS; + /* FIXME AC bias ? */ + dssdev->panel.timings = acx_panel_timings; + + if (dssdev->platform_enable) + dssdev->platform_enable(dssdev); + /* + * After reset we have to wait 5 msec before the first + * command can be sent. + */ + msleep(5); + + md->enabled = panel_enabled(md); + + r = panel_detect(md); + if (r) { + dev_err(&dssdev->dev, "%s panel detect error\n", __func__); + if (!md->enabled && dssdev->platform_disable) + dssdev->platform_disable(dssdev); + return r; + } + + mutex_lock(&acx_dev.mutex); + acx_dev.dssdev = dssdev; + mutex_unlock(&acx_dev.mutex); + + if (!md->enabled) { + if (dssdev->platform_disable) + dssdev->platform_disable(dssdev); + } + + /*------- Backlight control --------*/ + + props.fb_blank = FB_BLANK_UNBLANK; + props.power = FB_BLANK_UNBLANK; + + bldev = backlight_device_register("acx565akm", &md->spi->dev, + md, &acx565akm_bl_ops, &props); + md->bl_dev = bldev; + if (md->has_cabc) { + r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group); + if (r) { + dev_err(&bldev->dev, + "%s failed to create sysfs files\n", __func__); + backlight_device_unregister(bldev); + return r; + } + md->cabc_mode = get_hw_cabc_mode(md); + } + + if (md->has_bc) + max_brightness = 255; + else + max_brightness = dssdev->max_backlight_level; + + if (md->has_bc) + brightness = acx565akm_get_actual_brightness(md); + else if (dssdev->get_backlight) + brightness = dssdev->get_backlight(dssdev); + else + brightness = 0; + + bldev->props.max_brightness = max_brightness; + bldev->props.brightness = brightness; + + acx565akm_bl_update_status(bldev); + return 0; +} + +static void acx_panel_remove(struct omap_dss_device *dssdev) +{ + struct acx565akm_device *md = &acx_dev; + + dev_dbg(&dssdev->dev, "%s\n", __func__); + sysfs_remove_group(&md->bl_dev->dev.kobj, &bldev_attr_group); + backlight_device_unregister(md->bl_dev); + mutex_lock(&acx_dev.mutex); + acx_dev.dssdev = NULL; + mutex_unlock(&acx_dev.mutex); +} + +static int acx_panel_power_on(struct omap_dss_device *dssdev) +{ + struct acx565akm_device *md = &acx_dev; + int r; + + dev_dbg(&dssdev->dev, "%s\n", __func__); + + mutex_lock(&md->mutex); + + r = omapdss_sdi_display_enable(dssdev); + if (r) { + pr_err("%s sdi enable failed\n", __func__); + return r; + } + + /*FIXME tweak me */ + msleep(50); + + if (dssdev->platform_enable) { + r = dssdev->platform_enable(dssdev); + if (r) + goto fail; + } + + if (md->enabled) { + dev_dbg(&md->spi->dev, "panel already enabled\n"); + mutex_unlock(&md->mutex); + return 0; + } + + /* + * We have to meet all the following delay requirements: + * 1. tRW: reset pulse width 10usec (7.12.1) + * 2. tRT: reset cancel time 5msec (7.12.1) + * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst + * case (7.6.2) + * 4. 120msec before the sleep out command (7.12.1) + */ + msleep(120); + + set_sleep_mode(md, 0); + md->enabled = 1; + + /* 5msec between sleep out and the next command. (8.2.16) */ + msleep(5); + set_display_state(md, 1); + set_cabc_mode(md, md->cabc_mode); + + mutex_unlock(&md->mutex); + + return acx565akm_bl_update_status(md->bl_dev); +fail: + omapdss_sdi_display_disable(dssdev); + return r; +} + +static void acx_panel_power_off(struct omap_dss_device *dssdev) +{ + struct acx565akm_device *md = &acx_dev; + + dev_dbg(&dssdev->dev, "%s\n", __func__); + + mutex_lock(&md->mutex); + + if (!md->enabled) { + mutex_unlock(&md->mutex); + return; + } + set_display_state(md, 0); + set_sleep_mode(md, 1); + md->enabled = 0; + /* + * We have to provide PCLK,HS,VS signals for 2 frames (worst case + * ~50msec) after sending the sleep in command and asserting the + * reset signal. We probably could assert the reset w/o the delay + * but we still delay to avoid possible artifacts. (7.6.1) + */ + msleep(50); + + if (dssdev->platform_disable) + dssdev->platform_disable(dssdev); + + /* FIXME need to tweak this delay */ + msleep(100); + + omapdss_sdi_display_disable(dssdev); + + mutex_unlock(&md->mutex); +} + +static int acx_panel_enable(struct omap_dss_device *dssdev) +{ + int r; + + dev_dbg(&dssdev->dev, "%s\n", __func__); + r = acx_panel_power_on(dssdev); + + if (r) + return r; + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + return 0; +} + +static void acx_panel_disable(struct omap_dss_device *dssdev) +{ + dev_dbg(&dssdev->dev, "%s\n", __func__); + acx_panel_power_off(dssdev); + dssdev->state = OMAP_DSS_DISPLAY_DISABLED; +} + +static int acx_panel_suspend(struct omap_dss_device *dssdev) +{ + dev_dbg(&dssdev->dev, "%s\n", __func__); + acx_panel_power_off(dssdev); + dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; + return 0; +} + +static int acx_panel_resume(struct omap_dss_device *dssdev) +{ + int r; + + dev_dbg(&dssdev->dev, "%s\n", __func__); + r = acx_panel_power_on(dssdev); + if (r) + return r; + + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; + return 0; +} + +static void acx_panel_set_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + int r; + + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) + omapdss_sdi_display_disable(dssdev); + + dssdev->panel.timings = *timings; + + if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { + r = omapdss_sdi_display_enable(dssdev); + if (r) + dev_err(&dssdev->dev, "%s enable failed\n", __func__); + } +} + +static void acx_panel_get_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + *timings = dssdev->panel.timings; +} + +static int acx_panel_check_timings(struct omap_dss_device *dssdev, + struct omap_video_timings *timings) +{ + return 0; +} + + +static struct omap_dss_driver acx_panel_driver = { + .probe = acx_panel_probe, + .remove = acx_panel_remove, + + .enable = acx_panel_enable, + .disable = acx_panel_disable, + .suspend = acx_panel_suspend, + .resume = acx_panel_resume, + + .set_timings = acx_panel_set_timings, + .get_timings = acx_panel_get_timings, + .check_timings = acx_panel_check_timings, + + .get_recommended_bpp = acx_get_recommended_bpp, + + .driver = { + .name = "panel-acx565akm", + .owner = THIS_MODULE, + }, +}; + +/*--------------------SPI probe-------------------------*/ + +static int acx565akm_spi_probe(struct spi_device *spi) +{ + struct acx565akm_device *md = &acx_dev; + + dev_dbg(&spi->dev, "%s\n", __func__); + + spi->mode = SPI_MODE_3; + md->spi = spi; + mutex_init(&md->mutex); + dev_set_drvdata(&spi->dev, md); + + omap_dss_register_driver(&acx_panel_driver); + + return 0; +} + +static int acx565akm_spi_remove(struct spi_device *spi) +{ + struct acx565akm_device *md = dev_get_drvdata(&spi->dev); + + dev_dbg(&md->spi->dev, "%s\n", __func__); + omap_dss_unregister_driver(&acx_panel_driver); + + return 0; +} + +static struct spi_driver acx565akm_spi_driver = { + .driver = { + .name = "acx565akm", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = acx565akm_spi_probe, + .remove = __devexit_p(acx565akm_spi_remove), +}; + +static int __init acx565akm_init(void) +{ + return spi_register_driver(&acx565akm_spi_driver); +} + +static void __exit acx565akm_exit(void) +{ + spi_unregister_driver(&acx565akm_spi_driver); +} + +module_init(acx565akm_init); +module_exit(acx565akm_exit); + +MODULE_AUTHOR("Nokia Corporation"); +MODULE_DESCRIPTION("acx565akm LCD Driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From ac01bb7ea06a02c8dc9084b4ed59cb59efeceb39 Mon Sep 17 00:00:00 2001 From: Kishore Y Date: Sun, 25 Apr 2010 16:27:19 +0530 Subject: OMAP3630: DSS2: Updating MAX divider value In DPLL4 M3, M4, M5 and M6 field width has been increased by 1 bit in 3630. So the max divider value that can be achived will be 32 and not 16. In 3630 the functional clock is x1 of DPLL4 and not x2. Hence multiplier 2 is removed. Signed-off-by: Sudeep Basavaraj Signed-off-by: Mukund Mittal Signed-off-by: Kishore Y Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 54344184dd73..24b18258654f 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -223,7 +223,13 @@ void dss_dump_clocks(struct seq_file *s) seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); - seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n", + if (cpu_is_omap3630()) + seq_printf(s, "dss1_alwon_fclk = %lu / %lu = %lu\n", + dpll4_ck_rate, + dpll4_ck_rate / dpll4_m4_ck_rate, + dss_clk_get_rate(DSS_CLK_FCK1)); + else + seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n", dpll4_ck_rate, dpll4_ck_rate / dpll4_m4_ck_rate, dss_clk_get_rate(DSS_CLK_FCK1)); @@ -293,7 +299,8 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo) { unsigned long prate; - if (cinfo->fck_div > 16 || cinfo->fck_div == 0) + if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) || + cinfo->fck_div == 0) return -EINVAL; prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); @@ -329,7 +336,10 @@ int dss_get_clock_div(struct dss_clock_info *cinfo) if (cpu_is_omap34xx()) { unsigned long prate; prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); - cinfo->fck_div = prate / (cinfo->fck / 2); + if (cpu_is_omap3630()) + cinfo->fck_div = prate / (cinfo->fck); + else + cinfo->fck_div = prate / (cinfo->fck / 2); } else { cinfo->fck_div = 0; } @@ -402,10 +412,14 @@ retry: goto found; } else if (cpu_is_omap34xx()) { - for (fck_div = 16; fck_div > 0; --fck_div) { + for (fck_div = (cpu_is_omap3630() ? 32 : 16); + fck_div > 0; --fck_div) { struct dispc_clock_info cur_dispc; - fck = prate / fck_div * 2; + if (cpu_is_omap3630()) + fck = prate / fck_div; + else + fck = prate / fck_div * 2; if (fck > DISPC_MAX_FCK) continue; -- cgit v1.2.3 From a3bb67a75c0fe5c48def0fd39d2fe9ec043241d4 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Sun, 25 Apr 2010 12:53:35 +0200 Subject: OMAP2: DSS: Add missing line for update bg color The driver set the background color canvas but never writes it in DISPC_DEFAULT_COLOR_m register, which changes the background color on the LCD or TV. This patch adds a line to call to dispc_set_default_color() which is the function in charge to write the DISPC_DEFAULT_COLOR_m register. Signed-off-by: Carlos Lopez Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/manager.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 32ec2ff2e9cf..9e1fbe531bf0 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c @@ -843,6 +843,7 @@ static void configure_manager(enum omap_channel channel) c = &dss_cache.manager_cache[channel]; + dispc_set_default_color(channel, c->default_color); dispc_set_trans_key(channel, c->trans_key_type, c->trans_key); dispc_enable_trans_key(channel, c->trans_enabled); dispc_enable_alpha_blending(channel, c->alpha_enabled); -- cgit v1.2.3 From 368a148ea3833b540945fa53a63227c8ce76aa8f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 7 May 2010 11:58:41 +0200 Subject: OMAP: DSS2: omap_dss_probe() conditional compilation cleanup Move a number of #ifdefs from code into dss.h and elsewhere, and conditionally define no-op static inline functions, cleaning up the code. This style is according to Documentation/SubmittingPatches. Signed-off-by: Jani Nikula Acked-by: Kevin Hilman Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 35 ++++++++++------------------- drivers/video/omap2/dss/dss.h | 50 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 24 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 6d54467e5e20..92ee06742ece 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -482,6 +482,14 @@ static void dss_uninitialize_debugfs(void) if (dss_debugfs_dir) debugfs_remove_recursive(dss_debugfs_dir); } +#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ +static inline int dss_initialize_debugfs(void) +{ + return 0; +} +static inline void dss_uninitialize_debugfs(void) +{ +} #endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ /* PLATFORM DEVICE */ @@ -518,56 +526,47 @@ static int omap_dss_probe(struct platform_device *pdev) goto fail0; } -#ifdef CONFIG_OMAP2_DSS_RFBI r = rfbi_init(); if (r) { DSSERR("Failed to initialize rfbi\n"); goto fail0; } -#endif -#ifdef CONFIG_OMAP2_DSS_DPI r = dpi_init(pdev); if (r) { DSSERR("Failed to initialize dpi\n"); goto fail0; } -#endif r = dispc_init(); if (r) { DSSERR("Failed to initialize dispc\n"); goto fail0; } -#ifdef CONFIG_OMAP2_DSS_VENC + r = venc_init(pdev); if (r) { DSSERR("Failed to initialize venc\n"); goto fail0; } -#endif + if (cpu_is_omap34xx()) { -#ifdef CONFIG_OMAP2_DSS_SDI r = sdi_init(skip_init); if (r) { DSSERR("Failed to initialize SDI\n"); goto fail0; } -#endif -#ifdef CONFIG_OMAP2_DSS_DSI + r = dsi_init(pdev); if (r) { DSSERR("Failed to initialize DSI\n"); goto fail0; } -#endif } -#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) r = dss_initialize_debugfs(); if (r) goto fail0; -#endif for (i = 0; i < pdata->num_devices; ++i) { struct omap_dss_device *dssdev = pdata->devices[i]; @@ -595,27 +594,15 @@ static int omap_dss_remove(struct platform_device *pdev) int i; int c; -#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) dss_uninitialize_debugfs(); -#endif -#ifdef CONFIG_OMAP2_DSS_VENC venc_exit(); -#endif dispc_exit(); -#ifdef CONFIG_OMAP2_DSS_DPI dpi_exit(); -#endif -#ifdef CONFIG_OMAP2_DSS_RFBI rfbi_exit(); -#endif if (cpu_is_omap34xx()) { -#ifdef CONFIG_OMAP2_DSS_DSI dsi_exit(); -#endif -#ifdef CONFIG_OMAP2_DSS_SDI sdi_exit(); -#endif } dss_exit(); diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 24326a5fd292..786f433fd571 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -242,11 +242,22 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, struct dispc_clock_info *dispc_cinfo); /* SDI */ +#ifdef CONFIG_OMAP2_DSS_SDI int sdi_init(bool skip_init); void sdi_exit(void); int sdi_init_display(struct omap_dss_device *display); +#else +static inline int sdi_init(bool skip_init) +{ + return 0; +} +static inline void sdi_exit(void) +{ +} +#endif /* DSI */ +#ifdef CONFIG_OMAP2_DSS_DSI int dsi_init(struct platform_device *pdev); void dsi_exit(void); @@ -270,11 +281,30 @@ void dsi_pll_uninit(void); void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, u32 fifo_size, enum omap_burst_size *burst_size, u32 *fifo_low, u32 *fifo_high); +#else +static inline int dsi_init(struct platform_device *pdev) +{ + return 0; +} +static inline void dsi_exit(void) +{ +} +#endif /* DPI */ +#ifdef CONFIG_OMAP2_DSS_DPI int dpi_init(struct platform_device *pdev); void dpi_exit(void); int dpi_init_display(struct omap_dss_device *dssdev); +#else +static inline int dpi_init(struct platform_device *pdev) +{ + return 0; +} +static inline void dpi_exit(void) +{ +} +#endif /* DISPC */ int dispc_init(void); @@ -362,12 +392,23 @@ int dispc_get_clock_div(struct dispc_clock_info *cinfo); /* VENC */ +#ifdef CONFIG_OMAP2_DSS_VENC int venc_init(struct platform_device *pdev); void venc_exit(void); void venc_dump_regs(struct seq_file *s); int venc_init_display(struct omap_dss_device *display); +#else +static inline int venc_init(struct platform_device *pdev) +{ + return 0; +} +static inline void venc_exit(void) +{ +} +#endif /* RFBI */ +#ifdef CONFIG_OMAP2_DSS_RFBI int rfbi_init(void); void rfbi_exit(void); void rfbi_dump_regs(struct seq_file *s); @@ -379,6 +420,15 @@ void rfbi_transfer_area(u16 width, u16 height, void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); unsigned long rfbi_get_max_tx_rate(void); int rfbi_init_display(struct omap_dss_device *display); +#else +static inline int rfbi_init(void) +{ + return 0; +} +static inline void rfbi_exit(void) +{ +} +#endif #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS -- cgit v1.2.3 From fce064cbda85dda330150e8d4d9f6db1a3300023 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 7 May 2010 11:58:42 +0200 Subject: OMAP: DSS2: Fix omap_dss_probe() error path Perform graceful cleanup on errors instead of just bailing out. Signed-off-by: Jani Nikula Tested-by: Kevin Hilman Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 54 ++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 13 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 92ee06742ece..b3a498f22d36 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -507,7 +507,7 @@ static int omap_dss_probe(struct platform_device *pdev) r = dss_get_clocks(); if (r) - goto fail0; + goto err_clocks; dss_clk_enable_all_no_ctx(); @@ -523,57 +523,64 @@ static int omap_dss_probe(struct platform_device *pdev) r = dss_init(skip_init); if (r) { DSSERR("Failed to initialize DSS\n"); - goto fail0; + goto err_dss; } r = rfbi_init(); if (r) { DSSERR("Failed to initialize rfbi\n"); - goto fail0; + goto err_rfbi; } r = dpi_init(pdev); if (r) { DSSERR("Failed to initialize dpi\n"); - goto fail0; + goto err_dpi; } r = dispc_init(); if (r) { DSSERR("Failed to initialize dispc\n"); - goto fail0; + goto err_dispc; } r = venc_init(pdev); if (r) { DSSERR("Failed to initialize venc\n"); - goto fail0; + goto err_venc; } if (cpu_is_omap34xx()) { r = sdi_init(skip_init); if (r) { DSSERR("Failed to initialize SDI\n"); - goto fail0; + goto err_sdi; } r = dsi_init(pdev); if (r) { DSSERR("Failed to initialize DSI\n"); - goto fail0; + goto err_dsi; } } r = dss_initialize_debugfs(); if (r) - goto fail0; + goto err_debugfs; for (i = 0; i < pdata->num_devices; ++i) { struct omap_dss_device *dssdev = pdata->devices[i]; r = omap_dss_register_device(dssdev); - if (r) - DSSERR("device reg failed %d\n", i); + if (r) { + DSSERR("device %d %s register failed %d\n", i, + dssdev->name ?: "unnamed", r); + + while (--i >= 0) + omap_dss_unregister_device(pdata->devices[i]); + + goto err_register; + } if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0) pdata->default_device = dssdev; @@ -583,8 +590,29 @@ static int omap_dss_probe(struct platform_device *pdev) return 0; - /* XXX fail correctly */ -fail0: +err_register: + dss_uninitialize_debugfs(); +err_debugfs: + if (cpu_is_omap34xx()) + dsi_exit(); +err_dsi: + if (cpu_is_omap34xx()) + sdi_exit(); +err_sdi: + venc_exit(); +err_venc: + dispc_exit(); +err_dispc: + dpi_exit(); +err_dpi: + rfbi_exit(); +err_rfbi: + dss_exit(); +err_dss: + dss_clk_disable_all_no_ctx(); + dss_put_clocks(); +err_clocks: + return r; } -- cgit v1.2.3 From 2c3c8bea608866d8bd9dcf92657d57fdcac011c5 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Wed, 12 May 2010 18:28:57 -0700 Subject: sysfs: add struct file* to bin_attr callbacks This allows bin_attr->read,write,mmap callbacks to check file specific data (such as inode owner) as part of any privilege validation. Signed-off-by: Chris Wright Signed-off-by: Greg Kroah-Hartman --- arch/alpha/kernel/pci-sysfs.c | 8 ++++--- arch/mips/txx9/generic/setup.c | 4 ++-- arch/powerpc/sysdev/mv64x60_pci.c | 4 ++-- arch/s390/kernel/ipl.c | 14 ++++++------ drivers/acpi/system.c | 2 +- drivers/base/firmware_class.c | 11 ++++++---- drivers/firmware/dcdbas.c | 4 ++-- drivers/firmware/dell_rbu.c | 10 ++++----- drivers/firmware/efivars.c | 4 ++-- drivers/gpu/drm/drm_sysfs.c | 5 +++-- drivers/misc/c2port/core.c | 4 ++-- drivers/misc/ds1682.c | 6 ++++-- drivers/misc/eeprom/at24.c | 6 ++++-- drivers/misc/eeprom/at25.c | 6 ++++-- drivers/misc/eeprom/eeprom.c | 3 ++- drivers/misc/eeprom/max6875.c | 2 +- drivers/net/netxen/netxen_nic_main.c | 11 ++++++---- drivers/net/qlcnic/qlcnic_main.c | 12 +++++++---- drivers/pci/hotplug/acpiphp_ibm.c | 5 +++-- drivers/pci/pci-sysfs.c | 42 +++++++++++++++++++++++++----------- drivers/pcmcia/cistpl.c | 4 ++-- drivers/power/olpc_battery.c | 2 +- drivers/rapidio/rio-sysfs.c | 6 ++++-- drivers/rtc/rtc-cmos.c | 6 ++++-- drivers/rtc/rtc-ds1305.c | 6 ++++-- drivers/rtc/rtc-ds1307.c | 6 ++++-- drivers/rtc/rtc-ds1511.c | 10 +++++---- drivers/rtc/rtc-ds1553.c | 4 ++-- drivers/rtc/rtc-ds1742.c | 4 ++-- drivers/rtc/rtc-m48t59.c | 4 ++-- drivers/rtc/rtc-stk17ta8.c | 4 ++-- drivers/rtc/rtc-tx4939.c | 4 ++-- drivers/s390/cio/chp.c | 5 +++-- drivers/scsi/3w-sas.c | 4 ++-- drivers/scsi/arcmsr/arcmsr_attr.c | 9 +++++--- drivers/scsi/ibmvscsi/ibmvfc.c | 3 ++- drivers/scsi/ipr.c | 9 +++++--- drivers/scsi/lpfc/lpfc_attr.c | 20 ++++++++++++----- drivers/scsi/qla2xxx/qla_attr.c | 32 +++++++++++++-------------- drivers/staging/udlfb/udlfb.c | 3 ++- drivers/usb/core/sysfs.c | 3 ++- drivers/video/aty/radeon_base.c | 4 ++-- drivers/w1/slaves/w1_ds2431.c | 4 ++-- drivers/w1/slaves/w1_ds2433.c | 4 ++-- drivers/w1/slaves/w1_ds2760.c | 2 +- drivers/w1/w1.c | 4 ++-- drivers/zorro/zorro-sysfs.c | 2 +- fs/sysfs/bin.c | 24 ++++++++++----------- include/linux/sysfs.h | 7 +++--- kernel/ksysfs.c | 3 ++- kernel/module.c | 2 +- net/bridge/br_sysfs_br.c | 2 +- 52 files changed, 220 insertions(+), 149 deletions(-) (limited to 'drivers/video') diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c index d979e7c7bc4b..a5fffc882c72 100644 --- a/arch/alpha/kernel/pci-sysfs.c +++ b/arch/alpha/kernel/pci-sysfs.c @@ -53,6 +53,7 @@ static int __pci_mmap_fits(struct pci_dev *pdev, int num, /** * pci_mmap_resource - map a PCI resource into user memory space + * @filp: open sysfs file * @kobj: kobject for mapping * @attr: struct bin_attribute for the file being mapped * @vma: struct vm_area_struct passed into the mmap @@ -60,7 +61,8 @@ static int __pci_mmap_fits(struct pci_dev *pdev, int num, * * Use the bus mapping routines to map a PCI resource into userspace. */ -static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, +static int pci_mmap_resource(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, struct vm_area_struct *vma, int sparse) { struct pci_dev *pdev = to_pci_dev(container_of(kobj, @@ -89,14 +91,14 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, return hose_mmap_page_range(pdev->sysdata, vma, mmap_type, sparse); } -static int pci_mmap_resource_sparse(struct kobject *kobj, +static int pci_mmap_resource_sparse(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, struct vm_area_struct *vma) { return pci_mmap_resource(kobj, attr, vma, 1); } -static int pci_mmap_resource_dense(struct kobject *kobj, +static int pci_mmap_resource_dense(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, struct vm_area_struct *vma) { diff --git a/arch/mips/txx9/generic/setup.c b/arch/mips/txx9/generic/setup.c index adc69291f9e2..575d219b8001 100644 --- a/arch/mips/txx9/generic/setup.c +++ b/arch/mips/txx9/generic/setup.c @@ -905,7 +905,7 @@ struct txx9_sramc_sysdev { void __iomem *base; }; -static ssize_t txx9_sram_read(struct kobject *kobj, +static ssize_t txx9_sram_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) { @@ -920,7 +920,7 @@ static ssize_t txx9_sram_read(struct kobject *kobj, return size; } -static ssize_t txx9_sram_write(struct kobject *kobj, +static ssize_t txx9_sram_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) { diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c index 1456015a22d8..198f288570cc 100644 --- a/arch/powerpc/sysdev/mv64x60_pci.c +++ b/arch/powerpc/sysdev/mv64x60_pci.c @@ -24,7 +24,7 @@ #define MV64X60_VAL_LEN_MAX 11 #define MV64X60_PCICFG_CPCI_HOTSWAP 0x68 -static ssize_t mv64x60_hs_reg_read(struct kobject *kobj, +static ssize_t mv64x60_hs_reg_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { @@ -45,7 +45,7 @@ static ssize_t mv64x60_hs_reg_read(struct kobject *kobj, return sprintf(buf, "0x%08x\n", v); } -static ssize_t mv64x60_hs_reg_write(struct kobject *kobj, +static ssize_t mv64x60_hs_reg_write(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 72c8b0d070c8..a689070be287 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -403,8 +403,9 @@ static ssize_t sys_ipl_device_show(struct kobject *kobj, static struct kobj_attribute sys_ipl_device_attr = __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL); -static ssize_t ipl_parameter_read(struct kobject *kobj, struct bin_attribute *attr, - char *buf, loff_t off, size_t count) +static ssize_t ipl_parameter_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) { return memory_read_from_buffer(buf, count, &off, IPL_PARMBLOCK_START, IPL_PARMBLOCK_SIZE); @@ -419,8 +420,9 @@ static struct bin_attribute ipl_parameter_attr = { .read = &ipl_parameter_read, }; -static ssize_t ipl_scp_data_read(struct kobject *kobj, struct bin_attribute *attr, - char *buf, loff_t off, size_t count) +static ssize_t ipl_scp_data_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, + loff_t off, size_t count) { unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len; void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data; @@ -694,7 +696,7 @@ static struct kobj_attribute sys_reipl_ccw_vmparm_attr = /* FCP reipl device attributes */ -static ssize_t reipl_fcp_scpdata_read(struct kobject *kobj, +static ssize_t reipl_fcp_scpdata_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { @@ -704,7 +706,7 @@ static ssize_t reipl_fcp_scpdata_read(struct kobject *kobj, return memory_read_from_buffer(buf, count, &off, scp_data, size); } -static ssize_t reipl_fcp_scpdata_write(struct kobject *kobj, +static ssize_t reipl_fcp_scpdata_write(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index e35525b39f6b..c79e789ed03a 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -71,7 +71,7 @@ struct acpi_table_attr { struct list_head node; }; -static ssize_t acpi_table_show(struct kobject *kobj, +static ssize_t acpi_table_show(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t offset, size_t count) { diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index d98e424675cf..3f093b0dd217 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -278,8 +278,9 @@ static ssize_t firmware_loading_store(struct device *dev, static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); static ssize_t -firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr, - char *buffer, loff_t offset, size_t count) +firmware_data_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buffer, loff_t offset, + size_t count) { struct device *dev = to_dev(kobj); struct firmware_priv *fw_priv = dev_get_drvdata(dev); @@ -362,6 +363,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) /** * firmware_data_write - write method for firmware + * @filp: open sysfs file * @kobj: kobject for the device * @bin_attr: bin_attr structure * @buffer: buffer being written @@ -372,8 +374,9 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) * the driver as a firmware image. **/ static ssize_t -firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr, - char *buffer, loff_t offset, size_t count) +firmware_data_write(struct file* filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buffer, + loff_t offset, size_t count) { struct device *dev = to_dev(kobj); struct firmware_priv *fw_priv = dev_get_drvdata(dev); diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index fb09bb3c0ad6..aa9bc9e980e1 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c @@ -149,7 +149,7 @@ static ssize_t smi_data_buf_size_store(struct device *dev, return count; } -static ssize_t smi_data_read(struct kobject *kobj, +static ssize_t smi_data_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t count) { @@ -162,7 +162,7 @@ static ssize_t smi_data_read(struct kobject *kobj, return ret; } -static ssize_t smi_data_write(struct kobject *kobj, +static ssize_t smi_data_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t count) { diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index 3a4460265b10..2f452f1f7c8a 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -522,7 +522,7 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) rbu_data.image_update_buffer, rbu_data.bios_image_size); } -static ssize_t read_rbu_data(struct kobject *kobj, +static ssize_t read_rbu_data(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, loff_t pos, size_t count) { @@ -576,7 +576,7 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) release_firmware(fw); } -static ssize_t read_rbu_image_type(struct kobject *kobj, +static ssize_t read_rbu_image_type(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, loff_t pos, size_t count) { @@ -586,7 +586,7 @@ static ssize_t read_rbu_image_type(struct kobject *kobj, return size; } -static ssize_t write_rbu_image_type(struct kobject *kobj, +static ssize_t write_rbu_image_type(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, loff_t pos, size_t count) { @@ -647,7 +647,7 @@ static ssize_t write_rbu_image_type(struct kobject *kobj, return rc; } -static ssize_t read_rbu_packet_size(struct kobject *kobj, +static ssize_t read_rbu_packet_size(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, loff_t pos, size_t count) { @@ -660,7 +660,7 @@ static ssize_t read_rbu_packet_size(struct kobject *kobj, return size; } -static ssize_t write_rbu_packet_size(struct kobject *kobj, +static ssize_t write_rbu_packet_size(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, loff_t pos, size_t count) { diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 81b70bd07586..2a62ec6390e0 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -402,7 +402,7 @@ efivar_unregister(struct efivar_entry *var) } -static ssize_t efivar_create(struct kobject *kobj, +static ssize_t efivar_create(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t count) { @@ -461,7 +461,7 @@ static ssize_t efivar_create(struct kobject *kobj, return count; } -static ssize_t efivar_delete(struct kobject *kobj, +static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t count) { diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 25bbd30ed7af..387166d5a109 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -193,8 +193,9 @@ static ssize_t enabled_show(struct device *device, "disabled"); } -static ssize_t edid_show(struct kobject *kobj, struct bin_attribute *attr, - char *buf, loff_t off, size_t count) +static ssize_t edid_show(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, + size_t count) { struct device *connector_dev = container_of(kobj, struct device, kobj); struct drm_connector *connector = to_drm_connector(connector_dev); diff --git a/drivers/misc/c2port/core.c b/drivers/misc/c2port/core.c index ed090e77c9cd..19fc7c1cb428 100644 --- a/drivers/misc/c2port/core.c +++ b/drivers/misc/c2port/core.c @@ -707,7 +707,7 @@ static ssize_t __c2port_read_flash_data(struct c2port_device *dev, return nread; } -static ssize_t c2port_read_flash_data(struct kobject *kobj, +static ssize_t c2port_read_flash_data(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buffer, loff_t offset, size_t count) { @@ -824,7 +824,7 @@ static ssize_t __c2port_write_flash_data(struct c2port_device *dev, return nwrite; } -static ssize_t c2port_write_flash_data(struct kobject *kobj, +static ssize_t c2port_write_flash_data(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buffer, loff_t offset, size_t count) { diff --git a/drivers/misc/ds1682.c b/drivers/misc/ds1682.c index 9197cfc55015..a513f0aa6432 100644 --- a/drivers/misc/ds1682.c +++ b/drivers/misc/ds1682.c @@ -140,7 +140,8 @@ static const struct attribute_group ds1682_group = { /* * User data attribute */ -static ssize_t ds1682_eeprom_read(struct kobject *kobj, struct bin_attribute *attr, +static ssize_t ds1682_eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, size_t count) { struct i2c_client *client = kobj_to_i2c_client(kobj); @@ -163,7 +164,8 @@ static ssize_t ds1682_eeprom_read(struct kobject *kobj, struct bin_attribute *at return count; } -static ssize_t ds1682_eeprom_write(struct kobject *kobj, struct bin_attribute *attr, +static ssize_t ds1682_eeprom_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, size_t count) { struct i2c_client *client = kobj_to_i2c_client(kobj); diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index db7d0f21b65d..a79a62f75481 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -274,7 +274,8 @@ static ssize_t at24_read(struct at24_data *at24, return retval; } -static ssize_t at24_bin_read(struct kobject *kobj, struct bin_attribute *attr, +static ssize_t at24_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, size_t count) { struct at24_data *at24; @@ -395,7 +396,8 @@ static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off, return retval; } -static ssize_t at24_bin_write(struct kobject *kobj, struct bin_attribute *attr, +static ssize_t at24_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, size_t count) { struct at24_data *at24; diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index d194212a41f6..c627e4174ccd 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c @@ -126,7 +126,8 @@ at25_ee_read( } static ssize_t -at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr, +at25_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct device *dev; @@ -253,7 +254,8 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off, } static ssize_t -at25_bin_write(struct kobject *kobj, struct bin_attribute *bin_attr, +at25_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct device *dev; diff --git a/drivers/misc/eeprom/eeprom.c b/drivers/misc/eeprom/eeprom.c index e306a8cd2f96..45060ddc4e59 100644 --- a/drivers/misc/eeprom/eeprom.c +++ b/drivers/misc/eeprom/eeprom.c @@ -81,7 +81,8 @@ exit: mutex_unlock(&data->update_lock); } -static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr, +static ssize_t eeprom_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); diff --git a/drivers/misc/eeprom/max6875.c b/drivers/misc/eeprom/max6875.c index fe2909278507..5653a3ce0517 100644 --- a/drivers/misc/eeprom/max6875.c +++ b/drivers/misc/eeprom/max6875.c @@ -107,7 +107,7 @@ exit_up: mutex_unlock(&data->update_lock); } -static ssize_t max6875_read(struct kobject *kobj, +static ssize_t max6875_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index c61a61f177b7..6ce6ce1df6d2 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -2560,7 +2560,8 @@ netxen_sysfs_validate_crb(struct netxen_adapter *adapter, } static ssize_t -netxen_sysfs_read_crb(struct kobject *kobj, struct bin_attribute *attr, +netxen_sysfs_read_crb(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t offset, size_t size) { struct device *dev = container_of(kobj, struct device, kobj); @@ -2587,7 +2588,8 @@ netxen_sysfs_read_crb(struct kobject *kobj, struct bin_attribute *attr, } static ssize_t -netxen_sysfs_write_crb(struct kobject *kobj, struct bin_attribute *attr, +netxen_sysfs_write_crb(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t offset, size_t size) { struct device *dev = container_of(kobj, struct device, kobj); @@ -2627,7 +2629,8 @@ netxen_sysfs_validate_mem(struct netxen_adapter *adapter, } static ssize_t -netxen_sysfs_read_mem(struct kobject *kobj, struct bin_attribute *attr, +netxen_sysfs_read_mem(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t offset, size_t size) { struct device *dev = container_of(kobj, struct device, kobj); @@ -2647,7 +2650,7 @@ netxen_sysfs_read_mem(struct kobject *kobj, struct bin_attribute *attr, return size; } -static ssize_t netxen_sysfs_write_mem(struct kobject *kobj, +static ssize_t netxen_sysfs_write_mem(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t offset, size_t size) { diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 1003eb76fda3..23ea9caa5261 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -2464,7 +2464,8 @@ qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter, } static ssize_t -qlcnic_sysfs_read_crb(struct kobject *kobj, struct bin_attribute *attr, +qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t offset, size_t size) { struct device *dev = container_of(kobj, struct device, kobj); @@ -2488,7 +2489,8 @@ qlcnic_sysfs_read_crb(struct kobject *kobj, struct bin_attribute *attr, } static ssize_t -qlcnic_sysfs_write_crb(struct kobject *kobj, struct bin_attribute *attr, +qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t offset, size_t size) { struct device *dev = container_of(kobj, struct device, kobj); @@ -2525,7 +2527,8 @@ qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter, } static ssize_t -qlcnic_sysfs_read_mem(struct kobject *kobj, struct bin_attribute *attr, +qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t offset, size_t size) { struct device *dev = container_of(kobj, struct device, kobj); @@ -2546,7 +2549,8 @@ qlcnic_sysfs_read_mem(struct kobject *kobj, struct bin_attribute *attr, } static ssize_t -qlcnic_sysfs_write_mem(struct kobject *kobj, struct bin_attribute *attr, +qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t offset, size_t size) { struct device *dev = container_of(kobj, struct device, kobj); diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 6ecbfb27db9d..e525263210ee 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -108,7 +108,7 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status); static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status); static void ibm_handle_events(acpi_handle handle, u32 event, void *context); static int ibm_get_table_from_acpi(char **bufp); -static ssize_t ibm_read_apci_table(struct kobject *kobj, +static ssize_t ibm_read_apci_table(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, loff_t pos, size_t size); static acpi_status __init ibm_find_acpi_device(acpi_handle handle, @@ -351,6 +351,7 @@ read_table_done: /** * ibm_read_apci_table - callback for the sysfs apci_table file + * @filp: the open sysfs file * @kobj: the kobject this binary attribute is a part of * @bin_attr: struct bin_attribute for this file * @buffer: the kernel space buffer to fill @@ -364,7 +365,7 @@ read_table_done: * things get really tricky here... * our solution is to only allow reading the table in all at once. */ -static ssize_t ibm_read_apci_table(struct kobject *kobj, +static ssize_t ibm_read_apci_table(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buffer, loff_t pos, size_t size) { diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index fad93983bfed..ad44557e65c4 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -357,7 +357,8 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) struct device_attribute vga_attr = __ATTR_RO(boot_vga); static ssize_t -pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, +pci_read_config(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); @@ -430,7 +431,8 @@ pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, } static ssize_t -pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr, +pci_write_config(struct file* filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); @@ -487,7 +489,8 @@ pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr, } static ssize_t -read_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr, +read_vpd_attr(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct pci_dev *dev = @@ -502,7 +505,8 @@ read_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr, } static ssize_t -write_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr, +write_vpd_attr(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct pci_dev *dev = @@ -519,6 +523,7 @@ write_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr, #ifdef HAVE_PCI_LEGACY /** * pci_read_legacy_io - read byte(s) from legacy I/O port space + * @filp: open sysfs file * @kobj: kobject corresponding to file to read from * @bin_attr: struct bin_attribute for this file * @buf: buffer to store results @@ -529,7 +534,8 @@ write_vpd_attr(struct kobject *kobj, struct bin_attribute *bin_attr, * callback routine (pci_legacy_read). */ static ssize_t -pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, +pci_read_legacy_io(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct pci_bus *bus = to_pci_bus(container_of(kobj, @@ -545,6 +551,7 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, /** * pci_write_legacy_io - write byte(s) to legacy I/O port space + * @filp: open sysfs file * @kobj: kobject corresponding to file to read from * @bin_attr: struct bin_attribute for this file * @buf: buffer containing value to be written @@ -555,7 +562,8 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, * callback routine (pci_legacy_write). */ static ssize_t -pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, +pci_write_legacy_io(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct pci_bus *bus = to_pci_bus(container_of(kobj, @@ -570,6 +578,7 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, /** * pci_mmap_legacy_mem - map legacy PCI memory into user memory space + * @filp: open sysfs file * @kobj: kobject corresponding to device to be mapped * @attr: struct bin_attribute for this file * @vma: struct vm_area_struct passed to mmap @@ -579,7 +588,8 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr, * memory space. */ static int -pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr, +pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, struct vm_area_struct *vma) { struct pci_bus *bus = to_pci_bus(container_of(kobj, @@ -591,6 +601,7 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr, /** * pci_mmap_legacy_io - map legacy PCI IO into user memory space + * @filp: open sysfs file * @kobj: kobject corresponding to device to be mapped * @attr: struct bin_attribute for this file * @vma: struct vm_area_struct passed to mmap @@ -600,7 +611,8 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr, * memory space. Returns -ENOSYS if the operation isn't supported */ static int -pci_mmap_legacy_io(struct kobject *kobj, struct bin_attribute *attr, +pci_mmap_legacy_io(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, struct vm_area_struct *vma) { struct pci_bus *bus = to_pci_bus(container_of(kobj, @@ -750,14 +762,16 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, } static int -pci_mmap_resource_uc(struct kobject *kobj, struct bin_attribute *attr, +pci_mmap_resource_uc(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, struct vm_area_struct *vma) { return pci_mmap_resource(kobj, attr, vma, 0); } static int -pci_mmap_resource_wc(struct kobject *kobj, struct bin_attribute *attr, +pci_mmap_resource_wc(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, struct vm_area_struct *vma) { return pci_mmap_resource(kobj, attr, vma, 1); @@ -861,6 +875,7 @@ void __weak pci_remove_resource_files(struct pci_dev *dev) { return; } /** * pci_write_rom - used to enable access to the PCI ROM display + * @filp: sysfs file * @kobj: kernel object handle * @bin_attr: struct bin_attribute for this file * @buf: user input @@ -870,7 +885,8 @@ void __weak pci_remove_resource_files(struct pci_dev *dev) { return; } * writing anything except 0 enables it */ static ssize_t -pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr, +pci_write_rom(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); @@ -885,6 +901,7 @@ pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr, /** * pci_read_rom - read a PCI ROM + * @filp: sysfs file * @kobj: kernel object handle * @bin_attr: struct bin_attribute for this file * @buf: where to put the data we read from the ROM @@ -895,7 +912,8 @@ pci_write_rom(struct kobject *kobj, struct bin_attribute *bin_attr, * device corresponding to @kobj. */ static ssize_t -pci_read_rom(struct kobject *kobj, struct bin_attribute *bin_attr, +pci_read_rom(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 60d428be0b07..8844bc3e3118 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -1531,7 +1531,7 @@ static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf, } -static ssize_t pccard_show_cis(struct kobject *kobj, +static ssize_t pccard_show_cis(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -1562,7 +1562,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj, } -static ssize_t pccard_store_cis(struct kobject *kobj, +static ssize_t pccard_store_cis(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c index 8fefe5a73558..baefcf1cffc9 100644 --- a/drivers/power/olpc_battery.c +++ b/drivers/power/olpc_battery.c @@ -354,7 +354,7 @@ static enum power_supply_property olpc_bat_props[] = { #define EEPROM_END 0x80 #define EEPROM_SIZE (EEPROM_END - EEPROM_START) -static ssize_t olpc_bat_eeprom_read(struct kobject *kobj, +static ssize_t olpc_bat_eeprom_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) { uint8_t ec_byte; diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index ba742e82c57d..00b475658356 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -68,7 +68,8 @@ struct device_attribute rio_dev_attrs[] = { }; static ssize_t -rio_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, +rio_read_config(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct rio_dev *dev = @@ -139,7 +140,8 @@ rio_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, } static ssize_t -rio_write_config(struct kobject *kobj, struct bin_attribute *bin_attr, +rio_write_config(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct rio_dev *dev = diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index e9aa814ddd23..ece4dbddc0ea 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -519,7 +519,8 @@ static const struct rtc_class_ops cmos_rtc_ops = { #define NVRAM_OFFSET (RTC_REG_D + 1) static ssize_t -cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr, +cmos_nvram_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, size_t count) { int retval; @@ -547,7 +548,8 @@ cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr, } static ssize_t -cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr, +cmos_nvram_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, size_t count) { struct cmos_rtc *cmos; diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 7836c9cec557..48da85e97ca4 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -542,7 +542,8 @@ static void msg_init(struct spi_message *m, struct spi_transfer *x, } static ssize_t -ds1305_nvram_read(struct kobject *kobj, struct bin_attribute *attr, +ds1305_nvram_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, size_t count) { struct spi_device *spi; @@ -572,7 +573,8 @@ ds1305_nvram_read(struct kobject *kobj, struct bin_attribute *attr, } static ssize_t -ds1305_nvram_write(struct kobject *kobj, struct bin_attribute *attr, +ds1305_nvram_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, size_t count) { struct spi_device *spi; diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index c4ec5c158aa1..de033b7ac21f 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -556,7 +556,8 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { #define NVRAM_SIZE 56 static ssize_t -ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr, +ds1307_nvram_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, size_t count) { struct i2c_client *client; @@ -580,7 +581,8 @@ ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr, } static ssize_t -ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr, +ds1307_nvram_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, size_t count) { struct i2c_client *client; diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 06b8566c4532..37268e97de49 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c @@ -423,8 +423,9 @@ static const struct rtc_class_ops ds1511_rtc_ops = { }; static ssize_t -ds1511_nvram_read(struct kobject *kobj, struct bin_attribute *ba, - char *buf, loff_t pos, size_t size) +ds1511_nvram_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *ba, + char *buf, loff_t pos, size_t size) { ssize_t count; @@ -452,8 +453,9 @@ ds1511_nvram_read(struct kobject *kobj, struct bin_attribute *ba, } static ssize_t -ds1511_nvram_write(struct kobject *kobj, struct bin_attribute *bin_attr, - char *buf, loff_t pos, size_t size) +ds1511_nvram_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t pos, size_t size) { ssize_t count; diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 244f9994bcbb..ff432e2ca275 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -252,7 +252,7 @@ static const struct rtc_class_ops ds1553_rtc_ops = { .update_irq_enable = ds1553_rtc_update_irq_enable, }; -static ssize_t ds1553_nvram_read(struct kobject *kobj, +static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) { @@ -267,7 +267,7 @@ static ssize_t ds1553_nvram_read(struct kobject *kobj, return count; } -static ssize_t ds1553_nvram_write(struct kobject *kobj, +static ssize_t ds1553_nvram_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) { diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 2b4b0bc42d6f..042630c90dd3 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c @@ -128,7 +128,7 @@ static const struct rtc_class_ops ds1742_rtc_ops = { .set_time = ds1742_rtc_set_time, }; -static ssize_t ds1742_nvram_read(struct kobject *kobj, +static ssize_t ds1742_nvram_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) { @@ -143,7 +143,7 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, return count; } -static ssize_t ds1742_nvram_write(struct kobject *kobj, +static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) { diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 365ff3ac2348..be8359fdb65a 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c @@ -343,7 +343,7 @@ static const struct rtc_class_ops m48t02_rtc_ops = { .set_time = m48t59_rtc_set_time, }; -static ssize_t m48t59_nvram_read(struct kobject *kobj, +static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) { @@ -363,7 +363,7 @@ static ssize_t m48t59_nvram_read(struct kobject *kobj, return cnt; } -static ssize_t m48t59_nvram_write(struct kobject *kobj, +static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) { diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index b53a00198dbe..3b943673cd3e 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c @@ -244,7 +244,7 @@ static const struct rtc_class_ops stk17ta8_rtc_ops = { .alarm_irq_enable = stk17ta8_rtc_alarm_irq_enable, }; -static ssize_t stk17ta8_nvram_read(struct kobject *kobj, +static ssize_t stk17ta8_nvram_read(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t pos, size_t size) { @@ -259,7 +259,7 @@ static ssize_t stk17ta8_nvram_read(struct kobject *kobj, return count; } -static ssize_t stk17ta8_nvram_write(struct kobject *kobj, +static ssize_t stk17ta8_nvram_write(struct file *filp, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t pos, size_t size) { diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c index 20bfc64a15c8..ec6313d15359 100644 --- a/drivers/rtc/rtc-tx4939.c +++ b/drivers/rtc/rtc-tx4939.c @@ -188,7 +188,7 @@ static const struct rtc_class_ops tx4939_rtc_ops = { .alarm_irq_enable = tx4939_rtc_alarm_irq_enable, }; -static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj, +static ssize_t tx4939_rtc_nvram_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) { @@ -207,7 +207,7 @@ static ssize_t tx4939_rtc_nvram_read(struct kobject *kobj, return count; } -static ssize_t tx4939_rtc_nvram_write(struct kobject *kobj, +static ssize_t tx4939_rtc_nvram_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) { diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 1d16189f2f2d..6c9fa15aac7b 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -135,7 +135,8 @@ static int s390_vary_chpid(struct chp_id chpid, int on) /* * Channel measurement related functions */ -static ssize_t chp_measurement_chars_read(struct kobject *kobj, +static ssize_t chp_measurement_chars_read(struct file *filp, + struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -182,7 +183,7 @@ static void chp_measurement_copy_block(struct cmg_entry *buf, } while (reference_buf.values[0] != buf->values[0]); } -static ssize_t chp_measurement_read(struct kobject *kobj, +static ssize_t chp_measurement_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c index 54c5ffb1eaa1..d38000db9237 100644 --- a/drivers/scsi/3w-sas.c +++ b/drivers/scsi/3w-sas.c @@ -98,7 +98,7 @@ static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res /* Functions */ /* This function returns AENs through sysfs */ -static ssize_t twl_sysfs_aen_read(struct kobject *kobj, +static ssize_t twl_sysfs_aen_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *outbuf, loff_t offset, size_t count) { @@ -129,7 +129,7 @@ static struct bin_attribute twl_sysfs_aen_read_attr = { }; /* This function returns driver compatibility info through sysfs */ -static ssize_t twl_sysfs_compat_info(struct kobject *kobj, +static ssize_t twl_sysfs_compat_info(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *outbuf, loff_t offset, size_t count) { diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 5877f29a6005..a4e04c50c436 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -59,7 +59,8 @@ struct device_attribute *arcmsr_host_attrs[]; -static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, +static ssize_t arcmsr_sysfs_iop_message_read(struct file *filp, + struct kobject *kobj, struct bin_attribute *bin, char *buf, loff_t off, size_t count) @@ -105,7 +106,8 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, return (allxfer_len); } -static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj, +static ssize_t arcmsr_sysfs_iop_message_write(struct file *filp, + struct kobject *kobj, struct bin_attribute *bin, char *buf, loff_t off, size_t count) @@ -153,7 +155,8 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj, } } -static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj, +static ssize_t arcmsr_sysfs_iop_message_clear(struct file *filp, + struct kobject *kobj, struct bin_attribute *bin, char *buf, loff_t off, size_t count) diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index d18f45c95639..3eb2b7b3d8b0 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -2919,6 +2919,7 @@ static DEVICE_ATTR(log_level, S_IRUGO | S_IWUSR, #ifdef CONFIG_SCSI_IBMVFC_TRACE /** * ibmvfc_read_trace - Dump the adapter trace + * @filp: open sysfs file * @kobj: kobject struct * @bin_attr: bin_attribute struct * @buf: buffer @@ -2928,7 +2929,7 @@ static DEVICE_ATTR(log_level, S_IRUGO | S_IWUSR, * Return value: * number of bytes printed to buffer **/ -static ssize_t ibmvfc_read_trace(struct kobject *kobj, +static ssize_t ibmvfc_read_trace(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index b90c118119d7..6a6661c35b2f 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -3120,6 +3120,7 @@ restart: #ifdef CONFIG_SCSI_IPR_TRACE /** * ipr_read_trace - Dump the adapter trace + * @filp: open sysfs file * @kobj: kobject struct * @bin_attr: bin_attribute struct * @buf: buffer @@ -3129,7 +3130,7 @@ restart: * Return value: * number of bytes printed to buffer **/ -static ssize_t ipr_read_trace(struct kobject *kobj, +static ssize_t ipr_read_trace(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -3764,6 +3765,7 @@ static struct device_attribute *ipr_ioa_attrs[] = { #ifdef CONFIG_SCSI_IPR_DUMP /** * ipr_read_dump - Dump the adapter + * @filp: open sysfs file * @kobj: kobject struct * @bin_attr: bin_attribute struct * @buf: buffer @@ -3773,7 +3775,7 @@ static struct device_attribute *ipr_ioa_attrs[] = { * Return value: * number of bytes printed to buffer **/ -static ssize_t ipr_read_dump(struct kobject *kobj, +static ssize_t ipr_read_dump(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -3927,6 +3929,7 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) /** * ipr_write_dump - Setup dump state of adapter + * @filp: open sysfs file * @kobj: kobject struct * @bin_attr: bin_attribute struct * @buf: buffer @@ -3936,7 +3939,7 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) * Return value: * number of bytes printed to buffer **/ -static ssize_t ipr_write_dump(struct kobject *kobj, +static ssize_t ipr_write_dump(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 2e5f376d9ccc..bf33b315f93e 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -2643,6 +2643,7 @@ static DEVICE_ATTR(lpfc_stat_data_ctrl, S_IRUGO | S_IWUSR, /** * sysfs_drvr_stat_data_read - Read function for lpfc_drvr_stat_data attribute + * @filp: sysfs file * @kobj: Pointer to the kernel object * @bin_attr: Attribute object * @buff: Buffer pointer @@ -2654,7 +2655,8 @@ static DEVICE_ATTR(lpfc_stat_data_ctrl, S_IRUGO | S_IWUSR, * applications. **/ static ssize_t -sysfs_drvr_stat_data_read(struct kobject *kobj, struct bin_attribute *bin_attr, +sysfs_drvr_stat_data_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct device *dev = container_of(kobj, struct device, @@ -3362,6 +3364,7 @@ struct device_attribute *lpfc_vport_attrs[] = { /** * sysfs_ctlreg_write - Write method for writing to ctlreg + * @filp: open sysfs file * @kobj: kernel kobject that contains the kernel class device. * @bin_attr: kernel attributes passed to us. * @buf: contains the data to be written to the adapter IOREG space. @@ -3379,7 +3382,8 @@ struct device_attribute *lpfc_vport_attrs[] = { * value of count, buf contents written **/ static ssize_t -sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr, +sysfs_ctlreg_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { size_t buf_off; @@ -3415,6 +3419,7 @@ sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr, /** * sysfs_ctlreg_read - Read method for reading from ctlreg + * @filp: open sysfs file * @kobj: kernel kobject that contains the kernel class device. * @bin_attr: kernel attributes passed to us. * @buf: if successful contains the data from the adapter IOREG space. @@ -3431,7 +3436,8 @@ sysfs_ctlreg_write(struct kobject *kobj, struct bin_attribute *bin_attr, * value of count, buf contents read **/ static ssize_t -sysfs_ctlreg_read(struct kobject *kobj, struct bin_attribute *bin_attr, +sysfs_ctlreg_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { size_t buf_off; @@ -3496,6 +3502,7 @@ sysfs_mbox_idle(struct lpfc_hba *phba) /** * sysfs_mbox_write - Write method for writing information via mbox + * @filp: open sysfs file * @kobj: kernel kobject that contains the kernel class device. * @bin_attr: kernel attributes passed to us. * @buf: contains the data to be written to sysfs mbox. @@ -3516,7 +3523,8 @@ sysfs_mbox_idle(struct lpfc_hba *phba) * count number of bytes transferred **/ static ssize_t -sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr, +sysfs_mbox_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct device *dev = container_of(kobj, struct device, kobj); @@ -3571,6 +3579,7 @@ sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr, /** * sysfs_mbox_read - Read method for reading information via mbox + * @filp: open sysfs file * @kobj: kernel kobject that contains the kernel class device. * @bin_attr: kernel attributes passed to us. * @buf: contains the data to be read from sysfs mbox. @@ -3593,7 +3602,8 @@ sysfs_mbox_write(struct kobject *kobj, struct bin_attribute *bin_attr, * count number of bytes transferred **/ static ssize_t -sysfs_mbox_read(struct kobject *kobj, struct bin_attribute *bin_attr, +sysfs_mbox_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct device *dev = container_of(kobj, struct device, kobj); diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 3b708606b932..1e4cafabba15 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -16,7 +16,7 @@ static int qla24xx_vport_disable(struct fc_vport *, bool); /* SYSFS attributes --------------------------------------------------------- */ static ssize_t -qla2x00_sysfs_read_fw_dump(struct kobject *kobj, +qla2x00_sysfs_read_fw_dump(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -32,7 +32,7 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj, } static ssize_t -qla2x00_sysfs_write_fw_dump(struct kobject *kobj, +qla2x00_sysfs_write_fw_dump(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -92,7 +92,7 @@ static struct bin_attribute sysfs_fw_dump_attr = { }; static ssize_t -qla2x00_sysfs_read_nvram(struct kobject *kobj, +qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -111,7 +111,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, } static ssize_t -qla2x00_sysfs_write_nvram(struct kobject *kobj, +qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -177,7 +177,7 @@ static struct bin_attribute sysfs_nvram_attr = { }; static ssize_t -qla2x00_sysfs_read_optrom(struct kobject *kobj, +qla2x00_sysfs_read_optrom(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -193,7 +193,7 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj, } static ssize_t -qla2x00_sysfs_write_optrom(struct kobject *kobj, +qla2x00_sysfs_write_optrom(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -224,7 +224,7 @@ static struct bin_attribute sysfs_optrom_attr = { }; static ssize_t -qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, +qla2x00_sysfs_write_optrom_ctl(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -387,7 +387,7 @@ static struct bin_attribute sysfs_optrom_ctl_attr = { }; static ssize_t -qla2x00_sysfs_read_vpd(struct kobject *kobj, +qla2x00_sysfs_read_vpd(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -408,7 +408,7 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, } static ssize_t -qla2x00_sysfs_write_vpd(struct kobject *kobj, +qla2x00_sysfs_write_vpd(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -461,7 +461,7 @@ static struct bin_attribute sysfs_vpd_attr = { }; static ssize_t -qla2x00_sysfs_read_sfp(struct kobject *kobj, +qla2x00_sysfs_read_sfp(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -522,7 +522,7 @@ static struct bin_attribute sysfs_sfp_attr = { }; static ssize_t -qla2x00_sysfs_write_reset(struct kobject *kobj, +qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -592,7 +592,7 @@ static struct bin_attribute sysfs_reset_attr = { }; static ssize_t -qla2x00_sysfs_write_edc(struct kobject *kobj, +qla2x00_sysfs_write_edc(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -650,7 +650,7 @@ static struct bin_attribute sysfs_edc_attr = { }; static ssize_t -qla2x00_sysfs_write_edc_status(struct kobject *kobj, +qla2x00_sysfs_write_edc_status(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -700,7 +700,7 @@ qla2x00_sysfs_write_edc_status(struct kobject *kobj, } static ssize_t -qla2x00_sysfs_read_edc_status(struct kobject *kobj, +qla2x00_sysfs_read_edc_status(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -730,7 +730,7 @@ static struct bin_attribute sysfs_edc_status_attr = { }; static ssize_t -qla2x00_sysfs_read_xgmac_stats(struct kobject *kobj, +qla2x00_sysfs_read_xgmac_stats(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -782,7 +782,7 @@ static struct bin_attribute sysfs_xgmac_stats_attr = { }; static ssize_t -qla2x00_sysfs_read_dcbx_tlv(struct kobject *kobj, +qla2x00_sysfs_read_dcbx_tlv(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c index aa8195199a2c..577f2bf6eb23 100644 --- a/drivers/staging/udlfb/udlfb.c +++ b/drivers/staging/udlfb/udlfb.c @@ -1063,7 +1063,8 @@ static ssize_t metrics_misc_show(struct device *fbdev, atomic_read(&dev->lost_pixels) ? "yes" : "no"); } -static ssize_t edid_show(struct kobject *kobj, struct bin_attribute *a, +static ssize_t edid_show(struct file *filp, struct kobject *kobj, + struct bin_attribute *a, char *buf, loff_t off, size_t count) { struct device *fbdev = container_of(kobj, struct device, kobj); struct fb_info *fb_info = dev_get_drvdata(fbdev); diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 06863befaf3a..448f5b47fc48 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -658,7 +658,8 @@ const struct attribute_group *usb_device_groups[] = { /* Binary descriptors */ static ssize_t -read_descriptors(struct kobject *kobj, struct bin_attribute *attr, +read_descriptors(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, char *buf, loff_t off, size_t count) { struct device *dev = container_of(kobj, struct device, kobj); diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 6c37e8ee5efe..3c1e13ed1cba 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -2099,7 +2099,7 @@ static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u } -static ssize_t radeon_show_edid1(struct kobject *kobj, +static ssize_t radeon_show_edid1(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -2112,7 +2112,7 @@ static ssize_t radeon_show_edid1(struct kobject *kobj, } -static ssize_t radeon_show_edid2(struct kobject *kobj, +static ssize_t radeon_show_edid2(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { diff --git a/drivers/w1/slaves/w1_ds2431.c b/drivers/w1/slaves/w1_ds2431.c index 2c6c0cf6a20f..84e2410aec1d 100644 --- a/drivers/w1/slaves/w1_ds2431.c +++ b/drivers/w1/slaves/w1_ds2431.c @@ -96,7 +96,7 @@ static int w1_f2d_readblock(struct w1_slave *sl, int off, int count, char *buf) return -1; } -static ssize_t w1_f2d_read_bin(struct kobject *kobj, +static ssize_t w1_f2d_read_bin(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -202,7 +202,7 @@ retry: return 0; } -static ssize_t w1_f2d_write_bin(struct kobject *kobj, +static ssize_t w1_f2d_write_bin(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c index d2bf32118a98..0f7b8f9c509a 100644 --- a/drivers/w1/slaves/w1_ds2433.c +++ b/drivers/w1/slaves/w1_ds2433.c @@ -92,7 +92,7 @@ static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data, } #endif /* CONFIG_W1_SLAVE_DS2433_CRC */ -static ssize_t w1_f23_read_bin(struct kobject *kobj, +static ssize_t w1_f23_read_bin(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -206,7 +206,7 @@ static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data) return 0; } -static ssize_t w1_f23_write_bin(struct kobject *kobj, +static ssize_t w1_f23_write_bin(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { diff --git a/drivers/w1/slaves/w1_ds2760.c b/drivers/w1/slaves/w1_ds2760.c index 6e153343e117..483d45180911 100644 --- a/drivers/w1/slaves/w1_ds2760.c +++ b/drivers/w1/slaves/w1_ds2760.c @@ -97,7 +97,7 @@ int w1_ds2760_recall_eeprom(struct device *dev, int addr) return w1_ds2760_eeprom_cmd(dev, addr, W1_DS2760_RECALL_DATA); } -static ssize_t w1_ds2760_read_bin(struct kobject *kobj, +static ssize_t w1_ds2760_read_bin(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index ad5897dc4495..2839e281cd65 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -120,7 +120,7 @@ static struct device_attribute w1_slave_attr_id = /* Default family */ -static ssize_t w1_default_write(struct kobject *kobj, +static ssize_t w1_default_write(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -139,7 +139,7 @@ out_up: return count; } -static ssize_t w1_default_read(struct kobject *kobj, +static ssize_t w1_default_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index eb924e0a64ce..26f7184ef9e1 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c @@ -49,7 +49,7 @@ static ssize_t zorro_show_resource(struct device *dev, struct device_attribute * static DEVICE_ATTR(resource, S_IRUGO, zorro_show_resource, NULL); -static ssize_t zorro_read_config(struct kobject *kobj, +static ssize_t zorro_read_config(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 806b277453f9..4e321f7353fa 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -46,9 +46,9 @@ struct bin_buffer { }; static int -fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) +fill_read(struct file *file, char *buffer, loff_t off, size_t count) { - struct sysfs_dirent *attr_sd = dentry->d_fsdata; + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; int rc; @@ -59,7 +59,7 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count) rc = -EIO; if (attr->read) - rc = attr->read(kobj, attr, buffer, off, count); + rc = attr->read(file, kobj, attr, buffer, off, count); sysfs_put_active(attr_sd); @@ -70,8 +70,7 @@ static ssize_t read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off) { struct bin_buffer *bb = file->private_data; - struct dentry *dentry = file->f_path.dentry; - int size = dentry->d_inode->i_size; + int size = file->f_path.dentry->d_inode->i_size; loff_t offs = *off; int count = min_t(size_t, bytes, PAGE_SIZE); char *temp; @@ -92,7 +91,7 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off) mutex_lock(&bb->mutex); - count = fill_read(dentry, bb->buffer, offs, count); + count = fill_read(file, bb->buffer, offs, count); if (count < 0) { mutex_unlock(&bb->mutex); goto out_free; @@ -117,9 +116,9 @@ read(struct file *file, char __user *userbuf, size_t bytes, loff_t *off) } static int -flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) +flush_write(struct file *file, char *buffer, loff_t offset, size_t count) { - struct sysfs_dirent *attr_sd = dentry->d_fsdata; + struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata; struct bin_attribute *attr = attr_sd->s_bin_attr.bin_attr; struct kobject *kobj = attr_sd->s_parent->s_dir.kobj; int rc; @@ -130,7 +129,7 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count) rc = -EIO; if (attr->write) - rc = attr->write(kobj, attr, buffer, offset, count); + rc = attr->write(file, kobj, attr, buffer, offset, count); sysfs_put_active(attr_sd); @@ -141,8 +140,7 @@ static ssize_t write(struct file *file, const char __user *userbuf, size_t bytes, loff_t *off) { struct bin_buffer *bb = file->private_data; - struct dentry *dentry = file->f_path.dentry; - int size = dentry->d_inode->i_size; + int size = file->f_path.dentry->d_inode->i_size; loff_t offs = *off; int count = min_t(size_t, bytes, PAGE_SIZE); char *temp; @@ -165,7 +163,7 @@ static ssize_t write(struct file *file, const char __user *userbuf, memcpy(bb->buffer, temp, count); - count = flush_write(dentry, bb->buffer, offs, count); + count = flush_write(file, bb->buffer, offs, count); mutex_unlock(&bb->mutex); if (count > 0) @@ -363,7 +361,7 @@ static int mmap(struct file *file, struct vm_area_struct *vma) if (!attr->mmap) goto out_put; - rc = attr->mmap(kobj, attr, vma); + rc = attr->mmap(file, kobj, attr, vma); if (rc) goto out_put; diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 6903e9204032..f2694eb4dd3d 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -87,17 +87,18 @@ struct attribute_group { #define attr_name(_attr) (_attr).attr.name +struct file; struct vm_area_struct; struct bin_attribute { struct attribute attr; size_t size; void *private; - ssize_t (*read)(struct kobject *, struct bin_attribute *, + ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *, char *, loff_t, size_t); - ssize_t (*write)(struct kobject *, struct bin_attribute *, + ssize_t (*write)(struct file *,struct kobject *, struct bin_attribute *, char *, loff_t, size_t); - int (*mmap)(struct kobject *, struct bin_attribute *attr, + int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr, struct vm_area_struct *vma); }; diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 21fe3c426948..0b624e791805 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -138,7 +138,8 @@ extern const void __start_notes __attribute__((weak)); extern const void __stop_notes __attribute__((weak)); #define notes_size (&__stop_notes - &__start_notes) -static ssize_t notes_read(struct kobject *kobj, struct bin_attribute *bin_attr, +static ssize_t notes_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { memcpy(buf, &__start_notes + off, count); diff --git a/kernel/module.c b/kernel/module.c index e2564580f3f1..5e14483768bb 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1182,7 +1182,7 @@ struct module_notes_attrs { struct bin_attribute attrs[0]; }; -static ssize_t module_notes_read(struct kobject *kobj, +static ssize_t module_notes_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t count) { diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index dd321e39e621..486b8f3861d2 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -659,7 +659,7 @@ static struct attribute_group bridge_group = { * * Returns the number of bytes read. */ -static ssize_t brforward_read(struct kobject *kobj, +static ssize_t brforward_read(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { -- cgit v1.2.3 From f4b87dee923342505e1ddba8d34ce9de33e75050 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 21 May 2010 12:44:47 -0700 Subject: fbmem: avoid printk format warning with 32-bit resources Fix printk formats: drivers/video/fbmem.c: In function 'fb_do_apertures_overlap': drivers/video/fbmem.c:1494: warning: format '%llx' expects type 'long long unsigned int', but argument 2 has type 'resource_size_t' drivers/video/fbmem.c:1494: warning: format '%llx' expects type 'long long unsigned int', but argument 3 has type 'resource_size_t' drivers/video/fbmem.c:1494: warning: format '%llx' expects type 'long long unsigned int', but argument 4 has type 'resource_size_t' drivers/video/fbmem.c:1494: warning: format '%llx' expects type 'long long unsigned int', but argument 5 has type 'resource_size_t' Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- drivers/video/fbmem.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/video') diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index e08b7b5cb326..731fce64df9d 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1491,7 +1491,10 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena, for (j = 0; j < gena->count; ++j) { struct aperture *g = &gena->ranges[j]; printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n", - g->base, g->size, h->base, h->size); + (unsigned long long)g->base, + (unsigned long long)g->size, + (unsigned long long)h->base, + (unsigned long long)h->size); if (apertures_overlap(g, h)) return true; } -- cgit v1.2.3