162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de> 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci/* 662306a36Sopenharmony_ci * infrastructure for devices connected via I2C 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/slab.h> 1062306a36Sopenharmony_ci#include "via_aux.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistruct via_aux_bus *via_aux_probe(struct i2c_adapter *adap) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci struct via_aux_bus *bus; 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci if (!adap) 1862306a36Sopenharmony_ci return NULL; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci bus = kmalloc(sizeof(*bus), GFP_KERNEL); 2162306a36Sopenharmony_ci if (!bus) 2262306a36Sopenharmony_ci return NULL; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci bus->adap = adap; 2562306a36Sopenharmony_ci INIT_LIST_HEAD(&bus->drivers); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci via_aux_edid_probe(bus); 2862306a36Sopenharmony_ci via_aux_vt1636_probe(bus); 2962306a36Sopenharmony_ci via_aux_vt1632_probe(bus); 3062306a36Sopenharmony_ci via_aux_vt1631_probe(bus); 3162306a36Sopenharmony_ci via_aux_vt1625_probe(bus); 3262306a36Sopenharmony_ci via_aux_vt1622_probe(bus); 3362306a36Sopenharmony_ci via_aux_vt1621_probe(bus); 3462306a36Sopenharmony_ci via_aux_sii164_probe(bus); 3562306a36Sopenharmony_ci via_aux_ch7301_probe(bus); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci return bus; 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_civoid via_aux_free(struct via_aux_bus *bus) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci struct via_aux_drv *pos, *n; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci if (!bus) 4562306a36Sopenharmony_ci return; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci list_for_each_entry_safe(pos, n, &bus->drivers, chain) { 4862306a36Sopenharmony_ci if (pos->cleanup) 4962306a36Sopenharmony_ci pos->cleanup(pos); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci list_del(&pos->chain); 5262306a36Sopenharmony_ci kfree(pos->data); 5362306a36Sopenharmony_ci kfree(pos); 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci kfree(bus); 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciconst struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci struct via_aux_drv *pos; 6262306a36Sopenharmony_ci const struct fb_videomode *mode = NULL; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (!bus) 6562306a36Sopenharmony_ci return NULL; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci list_for_each_entry(pos, &bus->drivers, chain) { 6862306a36Sopenharmony_ci if (pos->get_preferred_mode) 6962306a36Sopenharmony_ci mode = pos->get_preferred_mode(pos); 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci return mode; 7362306a36Sopenharmony_ci} 74