From fe154ceebca982d317dd3bc3ee6f79dc63206abe Mon Sep 17 00:00:00 2001 From: Florian Tobias Schandinat Date: Sat, 30 Jul 2011 01:25:29 +0000 Subject: [PATCH] --- yaml --- r: 294283 b: refs/heads/master c: e75892715db800ee96fe4ac0407b73b57d866a68 h: refs/heads/master i: 294281: 0482a0f17ad312d0c150ae515cf41fbb0144dfa8 294279: a9d6c7ab46fa21832ba0148ab9d904034128ca19 v: v3 --- [refs] | 2 +- trunk/drivers/video/via/Makefile | 5 +- trunk/drivers/video/via/chip.h | 2 + trunk/drivers/video/via/dvi.c | 5 +- trunk/drivers/video/via/dvi.h | 3 +- trunk/drivers/video/via/hw.c | 85 ++++++++++++----------- trunk/drivers/video/via/hw.h | 3 +- trunk/drivers/video/via/lcd.c | 18 ++--- trunk/drivers/video/via/lcd.h | 3 +- trunk/drivers/video/via/via_aux.c | 68 ++++++++++++++++++ trunk/drivers/video/via/via_aux.h | 87 ++++++++++++++++++++++++ trunk/drivers/video/via/via_aux_ch7301.c | 50 ++++++++++++++ trunk/drivers/video/via/via_aux_edid.c | 40 +++++++++++ trunk/drivers/video/via/via_aux_sii164.c | 54 +++++++++++++++ trunk/drivers/video/via/via_aux_vt1621.c | 44 ++++++++++++ trunk/drivers/video/via/via_aux_vt1622.c | 50 ++++++++++++++ trunk/drivers/video/via/via_aux_vt1625.c | 50 ++++++++++++++ trunk/drivers/video/via/via_aux_vt1631.c | 46 +++++++++++++ trunk/drivers/video/via/via_aux_vt1632.c | 54 +++++++++++++++ trunk/drivers/video/via/via_aux_vt1636.c | 46 +++++++++++++ trunk/drivers/video/via/viafbdev.c | 27 ++++++++ trunk/drivers/video/via/viafbdev.h | 6 ++ 22 files changed, 685 insertions(+), 63 deletions(-) create mode 100644 trunk/drivers/video/via/via_aux.c create mode 100644 trunk/drivers/video/via/via_aux.h create mode 100644 trunk/drivers/video/via/via_aux_ch7301.c create mode 100644 trunk/drivers/video/via/via_aux_edid.c create mode 100644 trunk/drivers/video/via/via_aux_sii164.c create mode 100644 trunk/drivers/video/via/via_aux_vt1621.c create mode 100644 trunk/drivers/video/via/via_aux_vt1622.c create mode 100644 trunk/drivers/video/via/via_aux_vt1625.c create mode 100644 trunk/drivers/video/via/via_aux_vt1631.c create mode 100644 trunk/drivers/video/via/via_aux_vt1632.c create mode 100644 trunk/drivers/video/via/via_aux_vt1636.c diff --git a/[refs] b/[refs] index 8b78f79589ed..effcdd683fb3 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5b270d7bcbba26297abc38a3af566acbcc672ac6 +refs/heads/master: e75892715db800ee96fe4ac0407b73b57d866a68 diff --git a/trunk/drivers/video/via/Makefile b/trunk/drivers/video/via/Makefile index 5108136e8776..159f26e6adb5 100644 --- a/trunk/drivers/video/via/Makefile +++ b/trunk/drivers/video/via/Makefile @@ -6,4 +6,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 \ - via-core.o via-gpio.o via_modesetting.o via_clock.o + via-core.o via-gpio.o via_modesetting.o via_clock.o \ + via_aux.o via_aux_edid.o via_aux_vt1636.o via_aux_vt1632.o \ + via_aux_vt1631.o via_aux_vt1625.o via_aux_vt1622.o via_aux_vt1621.o \ + via_aux_sii164.o via_aux_ch7301.o diff --git a/trunk/drivers/video/via/chip.h b/trunk/drivers/video/via/chip.h index c2ecdb5a94da..3ebf20c06eef 100644 --- a/trunk/drivers/video/via/chip.h +++ b/trunk/drivers/video/via/chip.h @@ -146,6 +146,8 @@ struct tmds_setting_information { struct lvds_setting_information { int iga_path; + int h_active; + int v_active; int bpp; int lcd_panel_hres; int lcd_panel_vres; diff --git a/trunk/drivers/video/via/dvi.c b/trunk/drivers/video/via/dvi.c index 3312c81e861c..9138e517267c 100644 --- a/trunk/drivers/video/via/dvi.c +++ b/trunk/drivers/video/via/dvi.c @@ -172,8 +172,7 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) } /* DVI Set Mode */ -void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, - u16 cxres, u16 cyres, int iga) +void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga) { struct fb_var_screeninfo dvi_var = *var; struct crt_mode_table *rb_mode; @@ -186,7 +185,7 @@ void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, viafb_fill_var_timing_info(&dvi_var, rb_mode); } - viafb_fill_crtc_timing(&dvi_var, cxres, cyres, iga); + viafb_fill_crtc_timing(&dvi_var, iga); } /* Sense DVI Connector */ diff --git a/trunk/drivers/video/via/dvi.h b/trunk/drivers/video/via/dvi.h index db757850c216..e2116aaf797a 100644 --- a/trunk/drivers/video/via/dvi.h +++ b/trunk/drivers/video/via/dvi.h @@ -59,7 +59,6 @@ void viafb_dvi_enable(void); bool __devinit viafb_tmds_trasmitter_identify(void); void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, struct tmds_setting_information *tmds_setting); -void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, - u16 cxres, u16 cyres, int iga); +void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga); #endif /* __DVI_H__ */ diff --git a/trunk/drivers/video/via/hw.c b/trunk/drivers/video/via/hw.c index d35ced701396..d5aaca9cfa7e 100644 --- a/trunk/drivers/video/via/hw.c +++ b/trunk/drivers/video/via/hw.c @@ -1467,31 +1467,28 @@ void viafb_set_vclock(u32 clk, int set_iga) via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ } -static struct display_timing var_to_timing(const struct fb_var_screeninfo *var, u16 cxres, u16 cyres) +static struct display_timing var_to_timing(const struct fb_var_screeninfo *var) { struct display_timing timing; - u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2; - timing.hor_addr = cxres; - timing.hor_sync_start = timing.hor_addr + var->right_margin + dx; + timing.hor_addr = var->xres; + timing.hor_sync_start = timing.hor_addr + var->right_margin; timing.hor_sync_end = timing.hor_sync_start + var->hsync_len; - timing.hor_total = timing.hor_sync_end + var->left_margin + dx; - timing.hor_blank_start = timing.hor_addr + dx; - timing.hor_blank_end = timing.hor_total - dy; - timing.ver_addr = cyres; - timing.ver_sync_start = timing.ver_addr + var->lower_margin + dy; + timing.hor_total = timing.hor_sync_end + var->left_margin; + timing.hor_blank_start = timing.hor_addr; + timing.hor_blank_end = timing.hor_total; + timing.ver_addr = var->yres; + timing.ver_sync_start = timing.ver_addr + var->lower_margin; timing.ver_sync_end = timing.ver_sync_start + var->vsync_len; - timing.ver_total = timing.ver_sync_end + var->upper_margin + dy; - timing.ver_blank_start = timing.ver_addr + dy; - timing.ver_blank_end = timing.ver_total - dy; + timing.ver_total = timing.ver_sync_end + var->upper_margin; + timing.ver_blank_start = timing.ver_addr; + timing.ver_blank_end = timing.ver_total; return timing; } -void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, - u16 cxres, u16 cyres, int iga) +void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga) { - struct display_timing crt_reg = var_to_timing(var, - cxres ? cxres : var->xres, cyres ? cyres : var->yres); + struct display_timing crt_reg = var_to_timing(var); if (iga == IGA1) via_set_primary_timing(&crt_reg); @@ -1530,7 +1527,11 @@ void viafb_update_device_setting(int hres, int vres, int bpp, int flag) viaparinfo->tmds_setting_info->h_active = hres; viaparinfo->tmds_setting_info->v_active = vres; + viaparinfo->lvds_setting_info->h_active = hres; + viaparinfo->lvds_setting_info->v_active = vres; viaparinfo->lvds_setting_info->bpp = bpp; + viaparinfo->lvds_setting_info2->h_active = hres; + viaparinfo->lvds_setting_info2->v_active = vres; viaparinfo->lvds_setting_info2->bpp = bpp; } else { @@ -1539,11 +1540,16 @@ void viafb_update_device_setting(int hres, int vres, int bpp, int flag) viaparinfo->tmds_setting_info->v_active = vres; } - if (viaparinfo->lvds_setting_info->iga_path == IGA2) + if (viaparinfo->lvds_setting_info->iga_path == IGA2) { + viaparinfo->lvds_setting_info->h_active = hres; + viaparinfo->lvds_setting_info->v_active = vres; viaparinfo->lvds_setting_info->bpp = bpp; - - if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) + } + if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) { + viaparinfo->lvds_setting_info2->h_active = hres; + viaparinfo->lvds_setting_info2->v_active = vres; viaparinfo->lvds_setting_info2->bpp = bpp; + } } } @@ -1752,13 +1758,13 @@ static void set_display_channel(void) } } -static u8 get_sync(struct fb_var_screeninfo *var) +static u8 get_sync(struct fb_info *info) { u8 polarity = 0; - if (!(var->sync & FB_SYNC_HOR_HIGH_ACT)) + if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) polarity |= VIA_HSYNC_NEGATIVE; - if (!(var->sync & FB_SYNC_VERT_HIGH_ACT)) + if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) polarity |= VIA_VSYNC_NEGATIVE; return polarity; } @@ -1836,7 +1842,7 @@ static void hw_init(void) int viafb_setmode(int video_bpp, int video_bpp1) { - int j, cxres = 0, cyres = 0; + int j; int port; u32 devices = viaparinfo->shared->iga1_devices | viaparinfo->shared->iga2_devices; @@ -1885,8 +1891,6 @@ int viafb_setmode(int video_bpp, int video_bpp1) } else if (viafb_SAMM_ON) { viafb_fill_var_timing_info(&var2, viafb_get_best_mode( viafb_second_xres, viafb_second_yres, viafb_refresh1)); - cxres = viafbinfo->var.xres; - cyres = viafbinfo->var.yres; var2.bits_per_pixel = viafbinfo->var.bits_per_pixel; } @@ -1894,9 +1898,9 @@ int viafb_setmode(int video_bpp, int video_bpp1) if (viafb_CRT_ON) { if (viaparinfo->shared->iga2_devices & VIA_CRT && viafb_SAMM_ON) - viafb_fill_crtc_timing(&var2, cxres, cyres, IGA2); + viafb_fill_crtc_timing(&var2, IGA2); else - viafb_fill_crtc_timing(&viafbinfo->var, 0, 0, + viafb_fill_crtc_timing(&viafbinfo->var, (viaparinfo->shared->iga1_devices & VIA_CRT) ? IGA1 : IGA2); @@ -1914,9 +1918,9 @@ int viafb_setmode(int video_bpp, int video_bpp1) if (viafb_DVI_ON) { if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2 && viafb_SAMM_ON) - viafb_dvi_set_mode(&var2, cxres, cyres, IGA2); + viafb_dvi_set_mode(&var2, IGA2); else - viafb_dvi_set_mode(&viafbinfo->var, 0, 0, + viafb_dvi_set_mode(&viafbinfo->var, viaparinfo->tmds_setting_info->iga_path); } @@ -1924,8 +1928,7 @@ int viafb_setmode(int video_bpp, int video_bpp1) if (viafb_SAMM_ON && (viaparinfo->lvds_setting_info->iga_path == IGA2)) { viaparinfo->lvds_setting_info->bpp = video_bpp1; - viafb_lcd_set_mode(&var2, cxres, cyres, - viaparinfo->lvds_setting_info, + viafb_lcd_set_mode(viaparinfo->lvds_setting_info, &viaparinfo->chip_info->lvds_chip_info); } else { /* IGA1 doesn't have LCD scaling, so set it center. */ @@ -1934,8 +1937,7 @@ int viafb_setmode(int video_bpp, int video_bpp1) LCD_CENTERING; } viaparinfo->lvds_setting_info->bpp = video_bpp; - viafb_lcd_set_mode(&viafbinfo->var, 0, 0, - viaparinfo->lvds_setting_info, + viafb_lcd_set_mode(viaparinfo->lvds_setting_info, &viaparinfo->chip_info->lvds_chip_info); } } @@ -1943,8 +1945,7 @@ int viafb_setmode(int video_bpp, int video_bpp1) if (viafb_SAMM_ON && (viaparinfo->lvds_setting_info2->iga_path == IGA2)) { viaparinfo->lvds_setting_info2->bpp = video_bpp1; - viafb_lcd_set_mode(&var2, cxres, cyres, - viaparinfo->lvds_setting_info2, + viafb_lcd_set_mode(viaparinfo->lvds_setting_info2, &viaparinfo->chip_info->lvds_chip_info2); } else { /* IGA1 doesn't have LCD scaling, so set it center. */ @@ -1953,8 +1954,7 @@ int viafb_setmode(int video_bpp, int video_bpp1) LCD_CENTERING; } viaparinfo->lvds_setting_info2->bpp = video_bpp; - viafb_lcd_set_mode(&viafbinfo->var, 0, 0, - viaparinfo->lvds_setting_info2, + viafb_lcd_set_mode(viaparinfo->lvds_setting_info2, &viaparinfo->chip_info->lvds_chip_info2); } } @@ -1976,13 +1976,13 @@ int viafb_setmode(int video_bpp, int video_bpp1) viafb_DeviceStatus = CRT_Device; } device_on(); - if (!viafb_SAMM_ON) - via_set_sync_polarity(devices, get_sync(&viafbinfo->var)); + if (!viafb_dual_fb) + via_set_sync_polarity(devices, get_sync(viafbinfo)); else { via_set_sync_polarity(viaparinfo->shared->iga1_devices, - get_sync(&viafbinfo->var)); + get_sync(viafbinfo)); via_set_sync_polarity(viaparinfo->shared->iga2_devices, - get_sync(&var2)); + get_sync(viafbinfo1)); } clock.set_engine_pll_state(VIA_STATE_ON); @@ -2125,6 +2125,7 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ } } +/*According var's xres, yres fill var's other timing information*/ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, struct crt_mode_table *mode) { @@ -2133,8 +2134,6 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, crt_reg = mode->crtc; var->pixclock = 1000000000 / (crt_reg.hor_total * crt_reg.ver_total) * 1000 / mode->refresh_rate; - var->xres = crt_reg.hor_addr; - var->yres = crt_reg.ver_addr; var->left_margin = crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr; diff --git a/trunk/drivers/video/via/hw.h b/trunk/drivers/video/via/hw.h index f8129e49aa2c..4db5b6e8d8d0 100644 --- a/trunk/drivers/video/via/hw.h +++ b/trunk/drivers/video/via/hw.h @@ -637,8 +637,7 @@ extern int viafb_LCD_ON; extern int viafb_DVI_ON; extern int viafb_hotplug; -void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, - u16 cxres, u16 cyres, int iga); +void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga); void viafb_set_vclock(u32 CLK, int set_iga); void viafb_load_reg(int timing_value, int viafb_load_reg_num, struct io_register *reg, diff --git a/trunk/drivers/video/via/lcd.c b/trunk/drivers/video/via/lcd.c index 02cfdc8d7edd..5f3b4e394e82 100644 --- a/trunk/drivers/video/via/lcd.c +++ b/trunk/drivers/video/via/lcd.c @@ -55,7 +55,8 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, int panel_vres); static void via_pitch_alignment_patch_lcd( struct lvds_setting_information *plvds_setting_info, - struct lvds_chip_information *plvds_chip_info, int hres); + struct lvds_chip_information + *plvds_chip_info); static void lcd_patch_skew_dvp0(struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information *plvds_chip_info); @@ -455,13 +456,14 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, static void via_pitch_alignment_patch_lcd( struct lvds_setting_information *plvds_setting_info, - struct lvds_chip_information *plvds_chip_info, int hres) + struct lvds_chip_information + *plvds_chip_info) { unsigned char cr13, cr35, cr65, cr66, cr67; unsigned long dwScreenPitch = 0; unsigned long dwPitch; - dwPitch = hres * (plvds_setting_info->bpp >> 3); + dwPitch = plvds_setting_info->h_active * (plvds_setting_info->bpp >> 3); if (dwPitch & 0x1F) { dwScreenPitch = ((dwPitch + 31) & ~31) >> 3; if (plvds_setting_info->iga_path == IGA2) { @@ -546,14 +548,13 @@ static void lcd_patch_skew(struct lvds_setting_information } /* LCD Set Mode */ -void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres, - u16 cyres, struct lvds_setting_information *plvds_setting_info, +void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information *plvds_chip_info) { int set_iga = plvds_setting_info->iga_path; int mode_bpp = plvds_setting_info->bpp; - int set_hres = cxres ? cxres : var->xres; - int set_vres = cyres ? cyres : var->yres; + int set_hres = plvds_setting_info->h_active; + int set_vres = plvds_setting_info->v_active; int panel_hres = plvds_setting_info->lcd_panel_hres; int panel_vres = plvds_setting_info->lcd_panel_vres; u32 clock; @@ -612,8 +613,7 @@ void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres, viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0); /* Patch for non 32bit alignment mode */ - via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info, - set_hres); + via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info); } static void integrated_lvds_disable(struct lvds_setting_information diff --git a/trunk/drivers/video/via/lcd.h b/trunk/drivers/video/via/lcd.h index 8f3e4e06156c..77ca7b862e68 100644 --- a/trunk/drivers/video/via/lcd.h +++ b/trunk/drivers/video/via/lcd.h @@ -76,8 +76,7 @@ void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information *plvds_chip_info, struct lvds_setting_information *plvds_setting_info); -void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres, - u16 cyres, struct lvds_setting_information *plvds_setting_info, +void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info, struct lvds_chip_information *plvds_chip_info); bool __devinit viafb_lvds_trasmitter_identify(void); void viafb_init_lvds_output_interface(struct lvds_chip_information diff --git a/trunk/drivers/video/via/via_aux.c b/trunk/drivers/video/via/via_aux.c new file mode 100644 index 000000000000..e728b9bec235 --- /dev/null +++ b/trunk/drivers/video/via/via_aux.c @@ -0,0 +1,68 @@ +/* + * Copyright 2011 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. + */ +/* + * infrastructure for devices connected via I2C + */ + +#include +#include "via_aux.h" + + +struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap) +{ + struct via_aux_bus *bus; + + if (!adap) + return NULL; + + bus = kmalloc(sizeof(*bus), GFP_KERNEL); + if (!bus) + return NULL; + + bus->adap = adap; + INIT_LIST_HEAD(&bus->drivers); + + via_aux_edid_probe(bus); + via_aux_vt1636_probe(bus); + via_aux_vt1632_probe(bus); + via_aux_vt1631_probe(bus); + via_aux_vt1625_probe(bus); + via_aux_vt1622_probe(bus); + via_aux_vt1621_probe(bus); + via_aux_sii164_probe(bus); + via_aux_ch7301_probe(bus); + + return bus; +} + +void via_aux_free(struct via_aux_bus *bus) +{ + struct via_aux_drv *pos, *n; + + if (!bus) + return; + + list_for_each_entry_safe(pos, n, &bus->drivers, chain) { + list_del(&pos->chain); + kfree(pos); + } + + kfree(bus); +} diff --git a/trunk/drivers/video/via/via_aux.h b/trunk/drivers/video/via/via_aux.h new file mode 100644 index 000000000000..5a4867a2dcc3 --- /dev/null +++ b/trunk/drivers/video/via/via_aux.h @@ -0,0 +1,87 @@ +/* + * Copyright 2011 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. + */ +/* + * infrastructure for devices connected via I2C + */ + +#ifndef __VIA_AUX_H__ +#define __VIA_AUX_H__ + + +#include +#include + + +struct via_aux_bus { + struct i2c_adapter *adap; /* the I2C device to access the bus */ + struct list_head drivers; /* drivers for devices on this bus */ +}; + +struct via_aux_drv { + struct list_head chain; /* chain to support multiple drivers */ + + struct via_aux_bus *bus; /* the I2C bus used */ + u8 addr; /* the I2C slave address */ + + const char *name; /* human readable name of the driver */ + void *data; /* private data of this driver */ +}; + + +struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap); +void via_aux_free(struct via_aux_bus *bus); + + +static inline bool via_aux_add(struct via_aux_drv *drv) +{ + struct via_aux_drv *data = kmalloc(sizeof(*data), GFP_KERNEL); + + if (!data) + return false; + + *data = *drv; + list_add_tail(&data->chain, &data->bus->drivers); + return true; +} + +static inline bool via_aux_read(struct via_aux_drv *drv, u8 start, u8 *buf, + u8 len) +{ + struct i2c_msg msg[2] = { + {.addr = drv->addr, .flags = 0, .len = 1, .buf = &start}, + {.addr = drv->addr, .flags = I2C_M_RD, .len = len, .buf = buf} }; + + return i2c_transfer(drv->bus->adap, msg, 2) == 2; +} + + +/* probe functions of existing drivers - should only be called in via_aux.c */ +void via_aux_ch7301_probe(struct via_aux_bus *bus); +void via_aux_edid_probe(struct via_aux_bus *bus); +void via_aux_sii164_probe(struct via_aux_bus *bus); +void via_aux_vt1636_probe(struct via_aux_bus *bus); +void via_aux_vt1632_probe(struct via_aux_bus *bus); +void via_aux_vt1631_probe(struct via_aux_bus *bus); +void via_aux_vt1625_probe(struct via_aux_bus *bus); +void via_aux_vt1622_probe(struct via_aux_bus *bus); +void via_aux_vt1621_probe(struct via_aux_bus *bus); + + +#endif /* __VIA_AUX_H__ */ diff --git a/trunk/drivers/video/via/via_aux_ch7301.c b/trunk/drivers/video/via/via_aux_ch7301.c new file mode 100644 index 000000000000..1cbe5037a6b0 --- /dev/null +++ b/trunk/drivers/video/via/via_aux_ch7301.c @@ -0,0 +1,50 @@ +/* + * Copyright 2011 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. + */ +/* + * driver for Chrontel CH7301 DVI Transmitter + */ + +#include +#include "via_aux.h" + + +static const char *name = "CH7301 DVI Transmitter"; + + +static void probe(struct via_aux_bus *bus, u8 addr) +{ + struct via_aux_drv drv = { + .bus = bus, + .addr = addr, + .name = name}; + u8 tmp; + + if (!via_aux_read(&drv, 0x4B, &tmp, 1) || tmp != 0x17) + return; + + printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr); + via_aux_add(&drv); +} + +void via_aux_ch7301_probe(struct via_aux_bus *bus) +{ + probe(bus, 0x75); + probe(bus, 0x76); +} diff --git a/trunk/drivers/video/via/via_aux_edid.c b/trunk/drivers/video/via/via_aux_edid.c new file mode 100644 index 000000000000..547bff53a448 --- /dev/null +++ b/trunk/drivers/video/via/via_aux_edid.c @@ -0,0 +1,40 @@ +/* + * Copyright 2011 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. + */ +/* + * generic EDID driver + */ + +#include +#include "via_aux.h" + + +static const char *name = "EDID"; + + +void via_aux_edid_probe(struct via_aux_bus *bus) +{ + struct via_aux_drv drv = { + .bus = bus, + .addr = 0x50, + .name = name}; + + /* as EDID devices can be connected/disconnected just add the driver */ + via_aux_add(&drv); +} diff --git a/trunk/drivers/video/via/via_aux_sii164.c b/trunk/drivers/video/via/via_aux_sii164.c new file mode 100644 index 000000000000..ca1b35f033b1 --- /dev/null +++ b/trunk/drivers/video/via/via_aux_sii164.c @@ -0,0 +1,54 @@ +/* + * Copyright 2011 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. + */ +/* + * driver for Silicon Image SiI 164 PanelLink Transmitter + */ + +#include +#include "via_aux.h" + + +static const char *name = "SiI 164 PanelLink Transmitter"; + + +static void probe(struct via_aux_bus *bus, u8 addr) +{ + struct via_aux_drv drv = { + .bus = bus, + .addr = addr, + .name = name}; + /* check vendor id and device id */ + const u8 id[] = {0x01, 0x00, 0x06, 0x00}, len = ARRAY_SIZE(id); + u8 tmp[len]; + + if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len)) + return; + + printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr); + via_aux_add(&drv); +} + +void via_aux_sii164_probe(struct via_aux_bus *bus) +{ + u8 i; + + for (i = 0x38; i <= 0x3F; i++) + probe(bus, i); +} diff --git a/trunk/drivers/video/via/via_aux_vt1621.c b/trunk/drivers/video/via/via_aux_vt1621.c new file mode 100644 index 000000000000..38eca8479898 --- /dev/null +++ b/trunk/drivers/video/via/via_aux_vt1621.c @@ -0,0 +1,44 @@ +/* + * Copyright 2011 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. + */ +/* + * driver for VIA VT1621(M) TV Encoder + */ + +#include +#include "via_aux.h" + + +static const char *name = "VT1621(M) TV Encoder"; + + +void via_aux_vt1621_probe(struct via_aux_bus *bus) +{ + struct via_aux_drv drv = { + .bus = bus, + .addr = 0x20, + .name = name}; + u8 tmp; + + if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x02) + return; + + printk(KERN_INFO "viafb: Found %s\n", name); + via_aux_add(&drv); +} diff --git a/trunk/drivers/video/via/via_aux_vt1622.c b/trunk/drivers/video/via/via_aux_vt1622.c new file mode 100644 index 000000000000..8c79c68ba683 --- /dev/null +++ b/trunk/drivers/video/via/via_aux_vt1622.c @@ -0,0 +1,50 @@ +/* + * Copyright 2011 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. + */ +/* + * driver for VIA VT1622(M) Digital TV Encoder + */ + +#include +#include "via_aux.h" + + +static const char *name = "VT1622(M) Digital TV Encoder"; + + +static void probe(struct via_aux_bus *bus, u8 addr) +{ + struct via_aux_drv drv = { + .bus = bus, + .addr = addr, + .name = name}; + u8 tmp; + + if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x03) + return; + + printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr); + via_aux_add(&drv); +} + +void via_aux_vt1622_probe(struct via_aux_bus *bus) +{ + probe(bus, 0x20); + probe(bus, 0x21); +} diff --git a/trunk/drivers/video/via/via_aux_vt1625.c b/trunk/drivers/video/via/via_aux_vt1625.c new file mode 100644 index 000000000000..03eb30165d36 --- /dev/null +++ b/trunk/drivers/video/via/via_aux_vt1625.c @@ -0,0 +1,50 @@ +/* + * Copyright 2011 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. + */ +/* + * driver for VIA VT1625(M) HDTV Encoder + */ + +#include +#include "via_aux.h" + + +static const char *name = "VT1625(M) HDTV Encoder"; + + +static void probe(struct via_aux_bus *bus, u8 addr) +{ + struct via_aux_drv drv = { + .bus = bus, + .addr = addr, + .name = name}; + u8 tmp; + + if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x50) + return; + + printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr); + via_aux_add(&drv); +} + +void via_aux_vt1625_probe(struct via_aux_bus *bus) +{ + probe(bus, 0x20); + probe(bus, 0x21); +} diff --git a/trunk/drivers/video/via/via_aux_vt1631.c b/trunk/drivers/video/via/via_aux_vt1631.c new file mode 100644 index 000000000000..06e742f1f723 --- /dev/null +++ b/trunk/drivers/video/via/via_aux_vt1631.c @@ -0,0 +1,46 @@ +/* + * Copyright 2011 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. + */ +/* + * driver for VIA VT1631 LVDS Transmitter + */ + +#include +#include "via_aux.h" + + +static const char *name = "VT1631 LVDS Transmitter"; + + +void via_aux_vt1631_probe(struct via_aux_bus *bus) +{ + struct via_aux_drv drv = { + .bus = bus, + .addr = 0x38, + .name = name}; + /* check vendor id and device id */ + const u8 id[] = {0x06, 0x11, 0x91, 0x31}, len = ARRAY_SIZE(id); + u8 tmp[len]; + + if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len)) + return; + + printk(KERN_INFO "viafb: Found %s\n", name); + via_aux_add(&drv); +} diff --git a/trunk/drivers/video/via/via_aux_vt1632.c b/trunk/drivers/video/via/via_aux_vt1632.c new file mode 100644 index 000000000000..d24f4cd97401 --- /dev/null +++ b/trunk/drivers/video/via/via_aux_vt1632.c @@ -0,0 +1,54 @@ +/* + * Copyright 2011 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. + */ +/* + * driver for VIA VT1632 DVI Transmitter + */ + +#include +#include "via_aux.h" + + +static const char *name = "VT1632 DVI Transmitter"; + + +static void probe(struct via_aux_bus *bus, u8 addr) +{ + struct via_aux_drv drv = { + .bus = bus, + .addr = addr, + .name = name}; + /* check vendor id and device id */ + const u8 id[] = {0x06, 0x11, 0x92, 0x31}, len = ARRAY_SIZE(id); + u8 tmp[len]; + + if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len)) + return; + + printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr); + via_aux_add(&drv); +} + +void via_aux_vt1632_probe(struct via_aux_bus *bus) +{ + u8 i; + + for (i = 0x08; i <= 0x0F; i++) + probe(bus, i); +} diff --git a/trunk/drivers/video/via/via_aux_vt1636.c b/trunk/drivers/video/via/via_aux_vt1636.c new file mode 100644 index 000000000000..9e015c101d4d --- /dev/null +++ b/trunk/drivers/video/via/via_aux_vt1636.c @@ -0,0 +1,46 @@ +/* + * Copyright 2011 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. + */ +/* + * driver for VIA VT1636 LVDS Transmitter + */ + +#include +#include "via_aux.h" + + +static const char *name = "VT1636 LVDS Transmitter"; + + +void via_aux_vt1636_probe(struct via_aux_bus *bus) +{ + struct via_aux_drv drv = { + .bus = bus, + .addr = 0x40, + .name = name}; + /* check vendor id and device id */ + const u8 id[] = {0x06, 0x11, 0x45, 0x33}, len = ARRAY_SIZE(id); + u8 tmp[len]; + + if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len)) + return; + + printk(KERN_INFO "viafb: Found %s\n", name); + via_aux_add(&drv); +} diff --git a/trunk/drivers/video/via/viafbdev.c b/trunk/drivers/video/via/viafbdev.c index a13c258bd32f..6d5b64923236 100644 --- a/trunk/drivers/video/via/viafbdev.c +++ b/trunk/drivers/video/via/viafbdev.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #define _MASTER_FILE @@ -1729,6 +1730,29 @@ static struct viafb_pm_hooks viafb_fb_pm_hooks = { #endif +static void __devinit i2c_bus_probe(struct viafb_shared *shared) +{ + /* should be always CRT */ + printk(KERN_INFO "viafb: Probing I2C bus 0x26\n"); + shared->i2c_26 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_26)); + + /* seems to be usually DVP1 */ + printk(KERN_INFO "viafb: Probing I2C bus 0x31\n"); + shared->i2c_31 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_31)); + + /* FIXME: what is this? */ + printk(KERN_INFO "viafb: Probing I2C bus 0x2C\n"); + shared->i2c_2C = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_2C)); + + printk(KERN_INFO "viafb: Finished I2C bus probing"); +} + +static void i2c_bus_free(struct viafb_shared *shared) +{ + via_aux_free(shared->i2c_26); + via_aux_free(shared->i2c_31); + via_aux_free(shared->i2c_2C); +} int __devinit via_fb_pci_probe(struct viafb_dev *vdev) { @@ -1762,6 +1786,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) &viaparinfo->shared->lvds_setting_info2; viaparinfo->chip_info = &viaparinfo->shared->chip_info; + i2c_bus_probe(viaparinfo->shared); if (viafb_dual_fb) viafb_SAMM_ON = 1; parse_lcd_port(); @@ -1915,6 +1940,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) if (viafbinfo1) framebuffer_release(viafbinfo1); out_fb_release: + i2c_bus_free(viaparinfo->shared); framebuffer_release(viafbinfo); return rc; } @@ -1927,6 +1953,7 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev) if (viafb_dual_fb) unregister_framebuffer(viafbinfo1); viafb_remove_proc(viaparinfo->shared); + i2c_bus_free(viaparinfo->shared); framebuffer_release(viafbinfo); if (viafb_dual_fb) framebuffer_release(viafbinfo1); diff --git a/trunk/drivers/video/via/viafbdev.h b/trunk/drivers/video/via/viafbdev.h index d9440635d1d4..f6b2ddf56e94 100644 --- a/trunk/drivers/video/via/viafbdev.h +++ b/trunk/drivers/video/via/viafbdev.h @@ -26,6 +26,7 @@ #include #include +#include "via_aux.h" #include "ioctl.h" #include "share.h" #include "chip.h" @@ -48,6 +49,11 @@ struct viafb_shared { struct proc_dir_entry *iga2_proc_entry; struct viafb_dev *vdev; /* Global dev info */ + /* I2C busses that may have auxiliary devices */ + struct via_aux_bus *i2c_26; + struct via_aux_bus *i2c_31; + struct via_aux_bus *i2c_2C; + /* All the information will be needed to set engine */ struct tmds_setting_information tmds_setting_info; struct lvds_setting_information lvds_setting_info;