1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de> 4*4882a593Smuzhiyun */ 5*4882a593Smuzhiyun /* 6*4882a593Smuzhiyun * infrastructure for devices connected via I2C 7*4882a593Smuzhiyun */ 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun #include <linux/slab.h> 10*4882a593Smuzhiyun #include "via_aux.h" 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun via_aux_probe(struct i2c_adapter * adap)13*4882a593Smuzhiyunstruct via_aux_bus *via_aux_probe(struct i2c_adapter *adap) 14*4882a593Smuzhiyun { 15*4882a593Smuzhiyun struct via_aux_bus *bus; 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun if (!adap) 18*4882a593Smuzhiyun return NULL; 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun bus = kmalloc(sizeof(*bus), GFP_KERNEL); 21*4882a593Smuzhiyun if (!bus) 22*4882a593Smuzhiyun return NULL; 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun bus->adap = adap; 25*4882a593Smuzhiyun INIT_LIST_HEAD(&bus->drivers); 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun via_aux_edid_probe(bus); 28*4882a593Smuzhiyun via_aux_vt1636_probe(bus); 29*4882a593Smuzhiyun via_aux_vt1632_probe(bus); 30*4882a593Smuzhiyun via_aux_vt1631_probe(bus); 31*4882a593Smuzhiyun via_aux_vt1625_probe(bus); 32*4882a593Smuzhiyun via_aux_vt1622_probe(bus); 33*4882a593Smuzhiyun via_aux_vt1621_probe(bus); 34*4882a593Smuzhiyun via_aux_sii164_probe(bus); 35*4882a593Smuzhiyun via_aux_ch7301_probe(bus); 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun return bus; 38*4882a593Smuzhiyun } 39*4882a593Smuzhiyun via_aux_free(struct via_aux_bus * bus)40*4882a593Smuzhiyunvoid via_aux_free(struct via_aux_bus *bus) 41*4882a593Smuzhiyun { 42*4882a593Smuzhiyun struct via_aux_drv *pos, *n; 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun if (!bus) 45*4882a593Smuzhiyun return; 46*4882a593Smuzhiyun 47*4882a593Smuzhiyun list_for_each_entry_safe(pos, n, &bus->drivers, chain) { 48*4882a593Smuzhiyun if (pos->cleanup) 49*4882a593Smuzhiyun pos->cleanup(pos); 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun list_del(&pos->chain); 52*4882a593Smuzhiyun kfree(pos->data); 53*4882a593Smuzhiyun kfree(pos); 54*4882a593Smuzhiyun } 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun kfree(bus); 57*4882a593Smuzhiyun } 58*4882a593Smuzhiyun via_aux_get_preferred_mode(struct via_aux_bus * bus)59*4882a593Smuzhiyunconst struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus) 60*4882a593Smuzhiyun { 61*4882a593Smuzhiyun struct via_aux_drv *pos; 62*4882a593Smuzhiyun const struct fb_videomode *mode = NULL; 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun if (!bus) 65*4882a593Smuzhiyun return NULL; 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun list_for_each_entry(pos, &bus->drivers, chain) { 68*4882a593Smuzhiyun if (pos->get_preferred_mode) 69*4882a593Smuzhiyun mode = pos->get_preferred_mode(pos); 70*4882a593Smuzhiyun } 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun return mode; 73*4882a593Smuzhiyun } 74