cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

keywest.c (3684B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * common keywest i2c layer
      4 *
      5 * Copyright (c) by Takashi Iwai <tiwai@suse.de>
      6 */
      7
      8
      9#include <linux/init.h>
     10#include <linux/i2c.h>
     11#include <linux/delay.h>
     12#include <linux/module.h>
     13#include <sound/core.h>
     14#include "pmac.h"
     15
     16static struct pmac_keywest *keywest_ctx;
     17static bool keywest_probed;
     18
     19static int keywest_probe(struct i2c_client *client,
     20			 const struct i2c_device_id *id)
     21{
     22	keywest_probed = true;
     23	/* If instantiated via i2c-powermac, we still need to set the client */
     24	if (!keywest_ctx->client)
     25		keywest_ctx->client = client;
     26	i2c_set_clientdata(client, keywest_ctx);
     27	return 0;
     28}
     29
     30/*
     31 * This is kind of a hack, best would be to turn powermac to fixed i2c
     32 * bus numbers and declare the sound device as part of platform
     33 * initialization
     34 */
     35static int keywest_attach_adapter(struct i2c_adapter *adapter)
     36{
     37	struct i2c_board_info info;
     38	struct i2c_client *client;
     39
     40	if (! keywest_ctx)
     41		return -EINVAL;
     42
     43	if (strncmp(adapter->name, "mac-io", 6))
     44		return -EINVAL; /* ignored */
     45
     46	memset(&info, 0, sizeof(struct i2c_board_info));
     47	strscpy(info.type, "keywest", I2C_NAME_SIZE);
     48	info.addr = keywest_ctx->addr;
     49	client = i2c_new_client_device(adapter, &info);
     50	if (IS_ERR(client))
     51		return PTR_ERR(client);
     52	keywest_ctx->client = client;
     53
     54	/*
     55	 * We know the driver is already loaded, so the device should be
     56	 * already bound. If not it means binding failed, and then there
     57	 * is no point in keeping the device instantiated.
     58	 */
     59	if (!keywest_ctx->client->dev.driver) {
     60		i2c_unregister_device(keywest_ctx->client);
     61		keywest_ctx->client = NULL;
     62		return -ENODEV;
     63	}
     64	
     65	/*
     66	 * Let i2c-core delete that device on driver removal.
     67	 * This is safe because i2c-core holds the core_lock mutex for us.
     68	 */
     69	list_add_tail(&keywest_ctx->client->detected,
     70		      &to_i2c_driver(keywest_ctx->client->dev.driver)->clients);
     71	return 0;
     72}
     73
     74static int keywest_remove(struct i2c_client *client)
     75{
     76	if (! keywest_ctx)
     77		return 0;
     78	if (client == keywest_ctx->client)
     79		keywest_ctx->client = NULL;
     80
     81	return 0;
     82}
     83
     84
     85static const struct i2c_device_id keywest_i2c_id[] = {
     86	{ "MAC,tas3004", 0 },		/* instantiated by i2c-powermac */
     87	{ "keywest", 0 },		/* instantiated by us if needed */
     88	{ }
     89};
     90MODULE_DEVICE_TABLE(i2c, keywest_i2c_id);
     91
     92static struct i2c_driver keywest_driver = {
     93	.driver = {
     94		.name = "PMac Keywest Audio",
     95	},
     96	.probe = keywest_probe,
     97	.remove = keywest_remove,
     98	.id_table = keywest_i2c_id,
     99};
    100
    101/* exported */
    102void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c)
    103{
    104	if (keywest_ctx && keywest_ctx == i2c) {
    105		i2c_del_driver(&keywest_driver);
    106		keywest_ctx = NULL;
    107	}
    108}
    109
    110int snd_pmac_tumbler_post_init(void)
    111{
    112	int err;
    113	
    114	if (!keywest_ctx || !keywest_ctx->client)
    115		return -ENXIO;
    116
    117	err = keywest_ctx->init_client(keywest_ctx);
    118	if (err < 0) {
    119		snd_printk(KERN_ERR "tumbler: %i :cannot initialize the MCS\n", err);
    120		return err;
    121	}
    122	return 0;
    123}
    124
    125/* exported */
    126int snd_pmac_keywest_init(struct pmac_keywest *i2c)
    127{
    128	struct i2c_adapter *adap;
    129	int err, i = 0;
    130
    131	if (keywest_ctx)
    132		return -EBUSY;
    133
    134	adap = i2c_get_adapter(0);
    135	if (!adap)
    136		return -EPROBE_DEFER;
    137
    138	keywest_ctx = i2c;
    139
    140	err = i2c_add_driver(&keywest_driver);
    141	if (err) {
    142		snd_printk(KERN_ERR "cannot register keywest i2c driver\n");
    143		i2c_put_adapter(adap);
    144		return err;
    145	}
    146
    147	/* There was already a device from i2c-powermac. Great, let's return */
    148	if (keywest_probed)
    149		return 0;
    150
    151	/* We assume Macs have consecutive I2C bus numbers starting at 0 */
    152	while (adap) {
    153		/* Scan for devices to be bound to */
    154		err = keywest_attach_adapter(adap);
    155		if (!err)
    156			return 0;
    157		i2c_put_adapter(adap);
    158		adap = i2c_get_adapter(++i);
    159	}
    160
    161	return -ENODEV;
    162}