18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de> 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci/* 68c2ecf20Sopenharmony_ci * infrastructure for devices connected via I2C 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/slab.h> 108c2ecf20Sopenharmony_ci#include "via_aux.h" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cistruct via_aux_bus *via_aux_probe(struct i2c_adapter *adap) 148c2ecf20Sopenharmony_ci{ 158c2ecf20Sopenharmony_ci struct via_aux_bus *bus; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci if (!adap) 188c2ecf20Sopenharmony_ci return NULL; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci bus = kmalloc(sizeof(*bus), GFP_KERNEL); 218c2ecf20Sopenharmony_ci if (!bus) 228c2ecf20Sopenharmony_ci return NULL; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci bus->adap = adap; 258c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&bus->drivers); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci via_aux_edid_probe(bus); 288c2ecf20Sopenharmony_ci via_aux_vt1636_probe(bus); 298c2ecf20Sopenharmony_ci via_aux_vt1632_probe(bus); 308c2ecf20Sopenharmony_ci via_aux_vt1631_probe(bus); 318c2ecf20Sopenharmony_ci via_aux_vt1625_probe(bus); 328c2ecf20Sopenharmony_ci via_aux_vt1622_probe(bus); 338c2ecf20Sopenharmony_ci via_aux_vt1621_probe(bus); 348c2ecf20Sopenharmony_ci via_aux_sii164_probe(bus); 358c2ecf20Sopenharmony_ci via_aux_ch7301_probe(bus); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci return bus; 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_civoid via_aux_free(struct via_aux_bus *bus) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci struct via_aux_drv *pos, *n; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci if (!bus) 458c2ecf20Sopenharmony_ci return; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci list_for_each_entry_safe(pos, n, &bus->drivers, chain) { 488c2ecf20Sopenharmony_ci if (pos->cleanup) 498c2ecf20Sopenharmony_ci pos->cleanup(pos); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci list_del(&pos->chain); 528c2ecf20Sopenharmony_ci kfree(pos->data); 538c2ecf20Sopenharmony_ci kfree(pos); 548c2ecf20Sopenharmony_ci } 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci kfree(bus); 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ciconst struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci struct via_aux_drv *pos; 628c2ecf20Sopenharmony_ci const struct fb_videomode *mode = NULL; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci if (!bus) 658c2ecf20Sopenharmony_ci return NULL; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci list_for_each_entry(pos, &bus->drivers, chain) { 688c2ecf20Sopenharmony_ci if (pos->get_preferred_mode) 698c2ecf20Sopenharmony_ci mode = pos->get_preferred_mode(pos); 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci return mode; 738c2ecf20Sopenharmony_ci} 74