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