root/sound/ppc/keywest.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. keywest_probe
  2. keywest_attach_adapter
  3. keywest_remove
  4. snd_pmac_keywest_cleanup
  5. snd_pmac_tumbler_post_init
  6. snd_pmac_keywest_init

   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 
  16 /*
  17  * we have to keep a static variable here since i2c attach_adapter
  18  * callback cannot pass a private data.
  19  */
  20 static struct pmac_keywest *keywest_ctx;
  21 
  22 static bool keywest_probed;
  23 
  24 static int keywest_probe(struct i2c_client *client,
  25                          const struct i2c_device_id *id)
  26 {
  27         keywest_probed = true;
  28         /* If instantiated via i2c-powermac, we still need to set the client */
  29         if (!keywest_ctx->client)
  30                 keywest_ctx->client = client;
  31         i2c_set_clientdata(client, keywest_ctx);
  32         return 0;
  33 }
  34 
  35 /*
  36  * This is kind of a hack, best would be to turn powermac to fixed i2c
  37  * bus numbers and declare the sound device as part of platform
  38  * initialization
  39  */
  40 static int keywest_attach_adapter(struct i2c_adapter *adapter)
  41 {
  42         struct i2c_board_info info;
  43 
  44         if (! keywest_ctx)
  45                 return -EINVAL;
  46 
  47         if (strncmp(adapter->name, "mac-io", 6))
  48                 return -EINVAL; /* ignored */
  49 
  50         memset(&info, 0, sizeof(struct i2c_board_info));
  51         strlcpy(info.type, "keywest", I2C_NAME_SIZE);
  52         info.addr = keywest_ctx->addr;
  53         keywest_ctx->client = i2c_new_device(adapter, &info);
  54         if (!keywest_ctx->client)
  55                 return -ENODEV;
  56         /*
  57          * We know the driver is already loaded, so the device should be
  58          * already bound. If not it means binding failed, and then there
  59          * is no point in keeping the device instantiated.
  60          */
  61         if (!keywest_ctx->client->dev.driver) {
  62                 i2c_unregister_device(keywest_ctx->client);
  63                 keywest_ctx->client = NULL;
  64                 return -ENODEV;
  65         }
  66         
  67         /*
  68          * Let i2c-core delete that device on driver removal.
  69          * This is safe because i2c-core holds the core_lock mutex for us.
  70          */
  71         list_add_tail(&keywest_ctx->client->detected,
  72                       &to_i2c_driver(keywest_ctx->client->dev.driver)->clients);
  73         return 0;
  74 }
  75 
  76 static int keywest_remove(struct i2c_client *client)
  77 {
  78         if (! keywest_ctx)
  79                 return 0;
  80         if (client == keywest_ctx->client)
  81                 keywest_ctx->client = NULL;
  82 
  83         return 0;
  84 }
  85 
  86 
  87 static const struct i2c_device_id keywest_i2c_id[] = {
  88         { "MAC,tas3004", 0 },           /* instantiated by i2c-powermac */
  89         { "keywest", 0 },               /* instantiated by us if needed */
  90         { }
  91 };
  92 MODULE_DEVICE_TABLE(i2c, keywest_i2c_id);
  93 
  94 static struct i2c_driver keywest_driver = {
  95         .driver = {
  96                 .name = "PMac Keywest Audio",
  97         },
  98         .probe = keywest_probe,
  99         .remove = keywest_remove,
 100         .id_table = keywest_i2c_id,
 101 };
 102 
 103 /* exported */
 104 void snd_pmac_keywest_cleanup(struct pmac_keywest *i2c)
 105 {
 106         if (keywest_ctx && keywest_ctx == i2c) {
 107                 i2c_del_driver(&keywest_driver);
 108                 keywest_ctx = NULL;
 109         }
 110 }
 111 
 112 int snd_pmac_tumbler_post_init(void)
 113 {
 114         int err;
 115         
 116         if (!keywest_ctx || !keywest_ctx->client)
 117                 return -ENXIO;
 118 
 119         if ((err = keywest_ctx->init_client(keywest_ctx)) < 0) {
 120                 snd_printk(KERN_ERR "tumbler: %i :cannot initialize the MCS\n", err);
 121                 return err;
 122         }
 123         return 0;
 124 }
 125 
 126 /* exported */
 127 int snd_pmac_keywest_init(struct pmac_keywest *i2c)
 128 {
 129         struct i2c_adapter *adap;
 130         int err, i = 0;
 131 
 132         if (keywest_ctx)
 133                 return -EBUSY;
 134 
 135         adap = i2c_get_adapter(0);
 136         if (!adap)
 137                 return -EPROBE_DEFER;
 138 
 139         keywest_ctx = i2c;
 140 
 141         if ((err = i2c_add_driver(&keywest_driver))) {
 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 }

/* [<][>][^][v][top][bottom][index][help] */