^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * linux/drivers/video/savage/savagefb-i2c.c - S3 Savage DDC2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Based partly on rivafb-i2c.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * License. See the file COPYING in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "savagefb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define SAVAGE_DDC 0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define VGA_CR_IX 0x3d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define VGA_CR_DATA 0x3d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define CR_SERIAL1 0xa0 /* I2C serial communications interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define MM_SERIAL1 0xff20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define CR_SERIAL2 0xb1 /* DDC2 monitor communications interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* based on vt8365 documentation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define PROSAVAGE_I2C_ENAB 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define PROSAVAGE_I2C_SCL_OUT 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define PROSAVAGE_I2C_SDA_OUT 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define PROSAVAGE_I2C_SCL_IN 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define PROSAVAGE_I2C_SDA_IN 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define SAVAGE4_I2C_ENAB 0x00000020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define SAVAGE4_I2C_SCL_OUT 0x00000001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define SAVAGE4_I2C_SDA_OUT 0x00000002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define SAVAGE4_I2C_SCL_IN 0x00000008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define SAVAGE4_I2C_SDA_IN 0x00000010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static void savage4_gpio_setscl(void *data, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct savagefb_i2c_chan *chan = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) r = readl(chan->ioaddr + chan->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if(val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) r |= SAVAGE4_I2C_SCL_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) r &= ~SAVAGE4_I2C_SCL_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) writel(r, chan->ioaddr + chan->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) readl(chan->ioaddr + chan->reg); /* flush posted write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static void savage4_gpio_setsda(void *data, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct savagefb_i2c_chan *chan = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) r = readl(chan->ioaddr + chan->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if(val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) r |= SAVAGE4_I2C_SDA_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) r &= ~SAVAGE4_I2C_SDA_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) writel(r, chan->ioaddr + chan->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) readl(chan->ioaddr + chan->reg); /* flush posted write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static int savage4_gpio_getscl(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct savagefb_i2c_chan *chan = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SCL_IN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static int savage4_gpio_getsda(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct savagefb_i2c_chan *chan = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return (0 != (readl(chan->ioaddr + chan->reg) & SAVAGE4_I2C_SDA_IN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static void prosavage_gpio_setscl(void* data, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct savagefb_i2c_chan *chan = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u32 r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) r = VGArCR(chan->reg, chan->par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) r |= PROSAVAGE_I2C_ENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) r |= PROSAVAGE_I2C_SCL_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) r &= ~PROSAVAGE_I2C_SCL_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) VGAwCR(chan->reg, r, chan->par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static void prosavage_gpio_setsda(void* data, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct savagefb_i2c_chan *chan = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) unsigned int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) r = VGArCR(chan->reg, chan->par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) r |= PROSAVAGE_I2C_ENAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) r |= PROSAVAGE_I2C_SDA_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) r &= ~PROSAVAGE_I2C_SDA_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) VGAwCR(chan->reg, r, chan->par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static int prosavage_gpio_getscl(void* data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct savagefb_i2c_chan *chan = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SCL_IN) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int prosavage_gpio_getsda(void* data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct savagefb_i2c_chan *chan = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return (VGArCR(chan->reg, chan->par) & PROSAVAGE_I2C_SDA_IN) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (chan->par) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) strcpy(chan->adapter.name, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) chan->adapter.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) chan->adapter.algo_data = &chan->algo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) chan->adapter.dev.parent = &chan->par->pcidev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) chan->algo.udelay = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) chan->algo.timeout = 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) chan->algo.data = chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) i2c_set_adapdata(&chan->adapter, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /* Raise SCL and SDA */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) chan->algo.setsda(chan, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) chan->algo.setscl(chan, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) udelay(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) rc = i2c_bit_add_bus(&chan->adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) dev_dbg(&chan->par->pcidev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) "I2C bus %s registered.\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) dev_warn(&chan->par->pcidev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) "Failed to register I2C bus %s.\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) void savagefb_create_i2c_busses(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct savagefb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) par->chan.par = par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) switch (par->chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) case S3_PROSAVAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) case S3_PROSAVAGEDDR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) case S3_TWISTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) par->chan.reg = CR_SERIAL2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) par->chan.ioaddr = par->mmio.vbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) par->chan.algo.setsda = prosavage_gpio_setsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) par->chan.algo.setscl = prosavage_gpio_setscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) par->chan.algo.getsda = prosavage_gpio_getsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) par->chan.algo.getscl = prosavage_gpio_getscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) case S3_SAVAGE4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) par->chan.reg = CR_SERIAL1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (par->pcidev->revision > 1 && !(VGArCR(0xa6, par) & 0x40))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) par->chan.reg = CR_SERIAL2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) par->chan.ioaddr = par->mmio.vbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) par->chan.algo.setsda = prosavage_gpio_setsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) par->chan.algo.setscl = prosavage_gpio_setscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) par->chan.algo.getsda = prosavage_gpio_getsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) par->chan.algo.getscl = prosavage_gpio_getscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) case S3_SAVAGE2000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) par->chan.reg = MM_SERIAL1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) par->chan.ioaddr = par->mmio.vbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) par->chan.algo.setsda = savage4_gpio_setsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) par->chan.algo.setscl = savage4_gpio_setscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) par->chan.algo.getsda = savage4_gpio_getsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) par->chan.algo.getscl = savage4_gpio_getscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) par->chan.par = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) savage_setup_i2c_bus(&par->chan, "SAVAGE DDC2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) void savagefb_delete_i2c_busses(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) struct savagefb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (par->chan.par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) i2c_del_adapter(&par->chan.adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) par->chan.par = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct savagefb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) u8 *edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (par->chan.par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) edid = fb_ddc_read(&par->chan.adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) edid = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (!edid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* try to get from firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) const u8 *e = fb_firmware_edid(info->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) *out_edid = edid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return (edid) ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) MODULE_LICENSE("GPL");