root/drivers/video/fbdev/via/via_aux_edid.c

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

DEFINITIONS

This source file includes following definitions.
  1. query_edid
  2. get_preferred_mode
  3. cleanup
  4. via_aux_edid_probe

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
   4  */
   5 /*
   6  * generic EDID driver
   7  */
   8 
   9 #include <linux/slab.h>
  10 #include <linux/fb.h>
  11 #include "via_aux.h"
  12 #include "../edid.h"
  13 
  14 
  15 static const char *name = "EDID";
  16 
  17 
  18 static void query_edid(struct via_aux_drv *drv)
  19 {
  20         struct fb_monspecs *spec = drv->data;
  21         unsigned char edid[EDID_LENGTH];
  22         bool valid = false;
  23 
  24         if (spec) {
  25                 fb_destroy_modedb(spec->modedb);
  26         } else {
  27                 spec = kmalloc(sizeof(*spec), GFP_KERNEL);
  28                 if (!spec)
  29                         return;
  30         }
  31 
  32         spec->version = spec->revision = 0;
  33         if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) {
  34                 fb_edid_to_monspecs(edid, spec);
  35                 valid = spec->version || spec->revision;
  36         }
  37 
  38         if (!valid) {
  39                 kfree(spec);
  40                 spec = NULL;
  41         } else
  42                 printk(KERN_DEBUG "EDID: %s %s\n", spec->manufacturer, spec->monitor);
  43 
  44         drv->data = spec;
  45 }
  46 
  47 static const struct fb_videomode *get_preferred_mode(struct via_aux_drv *drv)
  48 {
  49         struct fb_monspecs *spec = drv->data;
  50         int i;
  51 
  52         if (!spec || !spec->modedb || !(spec->misc & FB_MISC_1ST_DETAIL))
  53                 return NULL;
  54 
  55         for (i = 0; i < spec->modedb_len; i++) {
  56                 if (spec->modedb[i].flag & FB_MODE_IS_FIRST &&
  57                         spec->modedb[i].flag & FB_MODE_IS_DETAILED)
  58                         return &spec->modedb[i];
  59         }
  60 
  61         return NULL;
  62 }
  63 
  64 static void cleanup(struct via_aux_drv *drv)
  65 {
  66         struct fb_monspecs *spec = drv->data;
  67 
  68         if (spec)
  69                 fb_destroy_modedb(spec->modedb);
  70 }
  71 
  72 void via_aux_edid_probe(struct via_aux_bus *bus)
  73 {
  74         struct via_aux_drv drv = {
  75                 .bus    =       bus,
  76                 .addr   =       0x50,
  77                 .name   =       name,
  78                 .cleanup        =       cleanup,
  79                 .get_preferred_mode     =       get_preferred_mode};
  80 
  81         query_edid(&drv);
  82 
  83         /* as EDID devices can be connected/disconnected just add the driver */
  84         via_aux_add(&drv);
  85 }

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