root/drivers/video/fbdev/core/fb_ddc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fb_do_probe_ddc_edid
  2. fb_ddc_read

   1 /*
   2  * drivers/video/fb_ddc.c - DDC/EDID read support.
   3  *
   4  *  Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com>
   5  *
   6  * This file is subject to the terms and conditions of the GNU General Public
   7  * License.  See the file COPYING in the main directory of this archive
   8  * for more details.
   9  */
  10 
  11 #include <linux/delay.h>
  12 #include <linux/device.h>
  13 #include <linux/module.h>
  14 #include <linux/fb.h>
  15 #include <linux/i2c-algo-bit.h>
  16 #include <linux/slab.h>
  17 
  18 #include "../edid.h"
  19 
  20 #define DDC_ADDR        0x50
  21 
  22 static unsigned char *fb_do_probe_ddc_edid(struct i2c_adapter *adapter)
  23 {
  24         unsigned char start = 0x0;
  25         unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
  26         struct i2c_msg msgs[] = {
  27                 {
  28                         .addr   = DDC_ADDR,
  29                         .flags  = 0,
  30                         .len    = 1,
  31                         .buf    = &start,
  32                 }, {
  33                         .addr   = DDC_ADDR,
  34                         .flags  = I2C_M_RD,
  35                         .len    = EDID_LENGTH,
  36                         .buf    = buf,
  37                 }
  38         };
  39 
  40         if (!buf) {
  41                 dev_warn(&adapter->dev, "unable to allocate memory for EDID "
  42                          "block.\n");
  43                 return NULL;
  44         }
  45 
  46         if (i2c_transfer(adapter, msgs, 2) == 2)
  47                 return buf;
  48 
  49         dev_warn(&adapter->dev, "unable to read EDID block.\n");
  50         kfree(buf);
  51         return NULL;
  52 }
  53 
  54 unsigned char *fb_ddc_read(struct i2c_adapter *adapter)
  55 {
  56         struct i2c_algo_bit_data *algo_data = adapter->algo_data;
  57         unsigned char *edid = NULL;
  58         int i, j;
  59 
  60         algo_data->setscl(algo_data->data, 1);
  61 
  62         for (i = 0; i < 3; i++) {
  63                 /* For some old monitors we need the
  64                  * following process to initialize/stop DDC
  65                  */
  66                 algo_data->setsda(algo_data->data, 1);
  67                 msleep(13);
  68 
  69                 algo_data->setscl(algo_data->data, 1);
  70                 if (algo_data->getscl) {
  71                         for (j = 0; j < 5; j++) {
  72                                 msleep(10);
  73                                 if (algo_data->getscl(algo_data->data))
  74                                         break;
  75                         }
  76                         if (j == 5)
  77                                 continue;
  78                 } else {
  79                         udelay(algo_data->udelay);
  80                 }
  81 
  82                 algo_data->setsda(algo_data->data, 0);
  83                 msleep(15);
  84                 algo_data->setscl(algo_data->data, 0);
  85                 msleep(15);
  86                 algo_data->setsda(algo_data->data, 1);
  87                 msleep(15);
  88 
  89                 /* Do the real work */
  90                 edid = fb_do_probe_ddc_edid(adapter);
  91                 algo_data->setsda(algo_data->data, 0);
  92                 algo_data->setscl(algo_data->data, 0);
  93                 msleep(15);
  94 
  95                 algo_data->setscl(algo_data->data, 1);
  96                 if (algo_data->getscl) {
  97                         for (j = 0; j < 10; j++) {
  98                                 msleep(10);
  99                                 if (algo_data->getscl(algo_data->data))
 100                                         break;
 101                         }
 102                 } else {
 103                         udelay(algo_data->udelay);
 104                 }
 105 
 106                 algo_data->setsda(algo_data->data, 1);
 107                 msleep(15);
 108                 algo_data->setscl(algo_data->data, 0);
 109                 algo_data->setsda(algo_data->data, 0);
 110                 if (edid)
 111                         break;
 112         }
 113         /* Release the DDC lines when done or the Apple Cinema HD display
 114          * will switch off
 115          */
 116         algo_data->setsda(algo_data->data, 1);
 117         algo_data->setscl(algo_data->data, 1);
 118 
 119         adapter->class |= I2C_CLASS_DDC;
 120         return edid;
 121 }
 122 
 123 EXPORT_SYMBOL_GPL(fb_ddc_read);
 124 
 125 MODULE_AUTHOR("Dennis Munsie <dmunsie@cecropia.com>");
 126 MODULE_DESCRIPTION("DDC/EDID reading support");
 127 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */