Loading drivers/video/via/via_aux.c +20 −0 Original line number Diff line number Diff line Loading @@ -60,9 +60,29 @@ void via_aux_free(struct via_aux_bus *bus) return; list_for_each_entry_safe(pos, n, &bus->drivers, chain) { if (pos->cleanup) pos->cleanup(pos); list_del(&pos->chain); kfree(pos->data); kfree(pos); } kfree(bus); } const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus) { struct via_aux_drv *pos; const struct fb_videomode *mode = NULL; if (!bus) return NULL; list_for_each_entry(pos, &bus->drivers, chain) { if (pos->get_preferred_mode) mode = pos->get_preferred_mode(pos); } return mode; } drivers/video/via/via_aux.h +6 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <linux/list.h> #include <linux/i2c.h> #include <linux/fb.h> struct via_aux_bus { Loading @@ -42,11 +43,16 @@ struct via_aux_drv { const char *name; /* human readable name of the driver */ void *data; /* private data of this driver */ void (*cleanup)(struct via_aux_drv *drv); const struct fb_videomode* (*get_preferred_mode) (struct via_aux_drv *drv); }; struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap); void via_aux_free(struct via_aux_bus *bus); const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus); static inline bool via_aux_add(struct via_aux_drv *drv) Loading drivers/video/via/via_aux_edid.c +58 −1 Original line number Diff line number Diff line Loading @@ -22,18 +22,75 @@ */ #include <linux/slab.h> #include <linux/fb.h> #include "via_aux.h" #include "../edid.h" static const char *name = "EDID"; static void query_edid(struct via_aux_drv *drv) { struct fb_monspecs *spec = drv->data; unsigned char edid[EDID_LENGTH]; bool valid = false; if (spec) fb_destroy_modedb(spec->modedb); else spec = kmalloc(sizeof(*spec), GFP_KERNEL); spec->version = spec->revision = 0; if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) { fb_edid_to_monspecs(edid, spec); valid = spec->version || spec->revision; } if (!valid) { kfree(spec); spec = NULL; } else printk(KERN_DEBUG "EDID: %s %s\n", spec->manufacturer, spec->monitor); drv->data = spec; } static const struct fb_videomode *get_preferred_mode(struct via_aux_drv *drv) { struct fb_monspecs *spec = drv->data; int i; if (!spec || !spec->modedb || !(spec->misc & FB_MISC_1ST_DETAIL)) return NULL; for (i = 0; i < spec->modedb_len; i++) { if (spec->modedb[i].flag & FB_MODE_IS_FIRST && spec->modedb[i].flag & FB_MODE_IS_DETAILED) return &spec->modedb[i]; } return NULL; } static void cleanup(struct via_aux_drv *drv) { struct fb_monspecs *spec = drv->data; if (spec) fb_destroy_modedb(spec->modedb); } void via_aux_edid_probe(struct via_aux_bus *bus) { struct via_aux_drv drv = { .bus = bus, .addr = 0x50, .name = name}; .name = name, .cleanup = cleanup, .get_preferred_mode = get_preferred_mode}; query_edid(&drv); /* as EDID devices can be connected/disconnected just add the driver */ via_aux_add(&drv); Loading drivers/video/via/viafbdev.c +19 −7 Original line number Diff line number Diff line Loading @@ -1671,12 +1671,23 @@ static void viafb_remove_proc(struct viafb_shared *shared) } #undef IS_VT1636 static int parse_mode(const char *str, u32 *xres, u32 *yres) static int parse_mode(const char *str, u32 devices, u32 *xres, u32 *yres) { const struct fb_videomode *mode = NULL; char *ptr; if (!str) { if (machine_is_olpc()) { if (devices == VIA_CRT) mode = via_aux_get_preferred_mode( viaparinfo->shared->i2c_26); else if (devices == VIA_DVP1) mode = via_aux_get_preferred_mode( viaparinfo->shared->i2c_31); if (mode) { *xres = mode->xres; *yres = mode->yres; } else if (machine_is_olpc()) { *xres = 1200; *yres = 900; } else { Loading Loading @@ -1829,10 +1840,11 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) viafb_second_size * 1024 * 1024; } parse_mode(viafb_mode, &default_xres, &default_yres); parse_mode(viafb_mode, viaparinfo->shared->iga1_devices, &default_xres, &default_yres); if (viafb_SAMM_ON == 1) parse_mode(viafb_mode1, &viafb_second_xres, &viafb_second_yres); parse_mode(viafb_mode1, viaparinfo->shared->iga2_devices, &viafb_second_xres, &viafb_second_yres); default_var.xres = default_xres; default_var.yres = default_yres; Loading Loading @@ -2060,9 +2072,9 @@ int __init viafb_init(void) if (r < 0) return r; #endif if (parse_mode(viafb_mode, &dummy_x, &dummy_y) if (parse_mode(viafb_mode, 0, &dummy_x, &dummy_y) || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh) || parse_mode(viafb_mode1, &dummy_x, &dummy_y) || parse_mode(viafb_mode1, 0, &dummy_x, &dummy_y) || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1) || viafb_bpp < 0 || viafb_bpp > 32 || viafb_bpp1 < 0 || viafb_bpp1 > 32 Loading Loading
drivers/video/via/via_aux.c +20 −0 Original line number Diff line number Diff line Loading @@ -60,9 +60,29 @@ void via_aux_free(struct via_aux_bus *bus) return; list_for_each_entry_safe(pos, n, &bus->drivers, chain) { if (pos->cleanup) pos->cleanup(pos); list_del(&pos->chain); kfree(pos->data); kfree(pos); } kfree(bus); } const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus) { struct via_aux_drv *pos; const struct fb_videomode *mode = NULL; if (!bus) return NULL; list_for_each_entry(pos, &bus->drivers, chain) { if (pos->get_preferred_mode) mode = pos->get_preferred_mode(pos); } return mode; }
drivers/video/via/via_aux.h +6 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <linux/list.h> #include <linux/i2c.h> #include <linux/fb.h> struct via_aux_bus { Loading @@ -42,11 +43,16 @@ struct via_aux_drv { const char *name; /* human readable name of the driver */ void *data; /* private data of this driver */ void (*cleanup)(struct via_aux_drv *drv); const struct fb_videomode* (*get_preferred_mode) (struct via_aux_drv *drv); }; struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap); void via_aux_free(struct via_aux_bus *bus); const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus); static inline bool via_aux_add(struct via_aux_drv *drv) Loading
drivers/video/via/via_aux_edid.c +58 −1 Original line number Diff line number Diff line Loading @@ -22,18 +22,75 @@ */ #include <linux/slab.h> #include <linux/fb.h> #include "via_aux.h" #include "../edid.h" static const char *name = "EDID"; static void query_edid(struct via_aux_drv *drv) { struct fb_monspecs *spec = drv->data; unsigned char edid[EDID_LENGTH]; bool valid = false; if (spec) fb_destroy_modedb(spec->modedb); else spec = kmalloc(sizeof(*spec), GFP_KERNEL); spec->version = spec->revision = 0; if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) { fb_edid_to_monspecs(edid, spec); valid = spec->version || spec->revision; } if (!valid) { kfree(spec); spec = NULL; } else printk(KERN_DEBUG "EDID: %s %s\n", spec->manufacturer, spec->monitor); drv->data = spec; } static const struct fb_videomode *get_preferred_mode(struct via_aux_drv *drv) { struct fb_monspecs *spec = drv->data; int i; if (!spec || !spec->modedb || !(spec->misc & FB_MISC_1ST_DETAIL)) return NULL; for (i = 0; i < spec->modedb_len; i++) { if (spec->modedb[i].flag & FB_MODE_IS_FIRST && spec->modedb[i].flag & FB_MODE_IS_DETAILED) return &spec->modedb[i]; } return NULL; } static void cleanup(struct via_aux_drv *drv) { struct fb_monspecs *spec = drv->data; if (spec) fb_destroy_modedb(spec->modedb); } void via_aux_edid_probe(struct via_aux_bus *bus) { struct via_aux_drv drv = { .bus = bus, .addr = 0x50, .name = name}; .name = name, .cleanup = cleanup, .get_preferred_mode = get_preferred_mode}; query_edid(&drv); /* as EDID devices can be connected/disconnected just add the driver */ via_aux_add(&drv); Loading
drivers/video/via/viafbdev.c +19 −7 Original line number Diff line number Diff line Loading @@ -1671,12 +1671,23 @@ static void viafb_remove_proc(struct viafb_shared *shared) } #undef IS_VT1636 static int parse_mode(const char *str, u32 *xres, u32 *yres) static int parse_mode(const char *str, u32 devices, u32 *xres, u32 *yres) { const struct fb_videomode *mode = NULL; char *ptr; if (!str) { if (machine_is_olpc()) { if (devices == VIA_CRT) mode = via_aux_get_preferred_mode( viaparinfo->shared->i2c_26); else if (devices == VIA_DVP1) mode = via_aux_get_preferred_mode( viaparinfo->shared->i2c_31); if (mode) { *xres = mode->xres; *yres = mode->yres; } else if (machine_is_olpc()) { *xres = 1200; *yres = 900; } else { Loading Loading @@ -1829,10 +1840,11 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) viafb_second_size * 1024 * 1024; } parse_mode(viafb_mode, &default_xres, &default_yres); parse_mode(viafb_mode, viaparinfo->shared->iga1_devices, &default_xres, &default_yres); if (viafb_SAMM_ON == 1) parse_mode(viafb_mode1, &viafb_second_xres, &viafb_second_yres); parse_mode(viafb_mode1, viaparinfo->shared->iga2_devices, &viafb_second_xres, &viafb_second_yres); default_var.xres = default_xres; default_var.yres = default_yres; Loading Loading @@ -2060,9 +2072,9 @@ int __init viafb_init(void) if (r < 0) return r; #endif if (parse_mode(viafb_mode, &dummy_x, &dummy_y) if (parse_mode(viafb_mode, 0, &dummy_x, &dummy_y) || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh) || parse_mode(viafb_mode1, &dummy_x, &dummy_y) || parse_mode(viafb_mode1, 0, &dummy_x, &dummy_y) || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1) || viafb_bpp < 0 || viafb_bpp > 32 || viafb_bpp1 < 0 || viafb_bpp1 > 32 Loading