Merge tag 'xfs-5.13-merge-5' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
[linux-2.6-microblaze.git] / drivers / mfd / wl1273-core.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * MFD driver for wl1273 FM radio and audio codec submodules.
4  *
5  * Copyright (C) 2011 Nokia Corporation
6  * Author: Matti Aaltonen <matti.j.aaltonen@nokia.com>
7  */
8
9 #include <linux/mfd/wl1273-core.h>
10 #include <linux/slab.h>
11 #include <linux/module.h>
12
13 #define DRIVER_DESC "WL1273 FM Radio Core"
14
15 static const struct i2c_device_id wl1273_driver_id_table[] = {
16         { WL1273_FM_DRIVER_NAME, 0 },
17         { }
18 };
19 MODULE_DEVICE_TABLE(i2c, wl1273_driver_id_table);
20
21 static int wl1273_fm_read_reg(struct wl1273_core *core, u8 reg, u16 *value)
22 {
23         struct i2c_client *client = core->client;
24         u8 b[2];
25         int r;
26
27         r = i2c_smbus_read_i2c_block_data(client, reg, sizeof(b), b);
28         if (r != 2) {
29                 dev_err(&client->dev, "%s: Read: %d fails.\n", __func__, reg);
30                 return -EREMOTEIO;
31         }
32
33         *value = (u16)b[0] << 8 | b[1];
34
35         return 0;
36 }
37
38 static int wl1273_fm_write_cmd(struct wl1273_core *core, u8 cmd, u16 param)
39 {
40         struct i2c_client *client = core->client;
41         u8 buf[] = { (param >> 8) & 0xff, param & 0xff };
42         int r;
43
44         r = i2c_smbus_write_i2c_block_data(client, cmd, sizeof(buf), buf);
45         if (r) {
46                 dev_err(&client->dev, "%s: Cmd: %d fails.\n", __func__, cmd);
47                 return r;
48         }
49
50         return 0;
51 }
52
53 static int wl1273_fm_write_data(struct wl1273_core *core, u8 *data, u16 len)
54 {
55         struct i2c_client *client = core->client;
56         struct i2c_msg msg;
57         int r;
58
59         msg.addr = client->addr;
60         msg.flags = 0;
61         msg.buf = data;
62         msg.len = len;
63
64         r = i2c_transfer(client->adapter, &msg, 1);
65         if (r != 1) {
66                 dev_err(&client->dev, "%s: write error.\n", __func__);
67                 return -EREMOTEIO;
68         }
69
70         return 0;
71 }
72
73 /**
74  * wl1273_fm_set_audio() -      Set audio mode.
75  * @core:                       A pointer to the device struct.
76  * @new_mode:                   The new audio mode.
77  *
78  * Audio modes are WL1273_AUDIO_DIGITAL and WL1273_AUDIO_ANALOG.
79  */
80 static int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode)
81 {
82         int r = 0;
83
84         if (core->mode == WL1273_MODE_OFF ||
85             core->mode == WL1273_MODE_SUSPENDED)
86                 return -EPERM;
87
88         if (core->mode == WL1273_MODE_RX && new_mode == WL1273_AUDIO_DIGITAL) {
89                 r = wl1273_fm_write_cmd(core, WL1273_PCM_MODE_SET,
90                                         WL1273_PCM_DEF_MODE);
91                 if (r)
92                         goto out;
93
94                 r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
95                                         core->i2s_mode);
96                 if (r)
97                         goto out;
98
99                 r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
100                                         WL1273_AUDIO_ENABLE_I2S);
101                 if (r)
102                         goto out;
103
104         } else if (core->mode == WL1273_MODE_RX &&
105                    new_mode == WL1273_AUDIO_ANALOG) {
106                 r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
107                                         WL1273_AUDIO_ENABLE_ANALOG);
108                 if (r)
109                         goto out;
110
111         } else if (core->mode == WL1273_MODE_TX &&
112                    new_mode == WL1273_AUDIO_DIGITAL) {
113                 r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
114                                         core->i2s_mode);
115                 if (r)
116                         goto out;
117
118                 r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
119                                         WL1273_AUDIO_IO_SET_I2S);
120                 if (r)
121                         goto out;
122
123         } else if (core->mode == WL1273_MODE_TX &&
124                    new_mode == WL1273_AUDIO_ANALOG) {
125                 r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
126                                         WL1273_AUDIO_IO_SET_ANALOG);
127                 if (r)
128                         goto out;
129         }
130
131         core->audio_mode = new_mode;
132 out:
133         return r;
134 }
135
136 /**
137  * wl1273_fm_set_volume() -     Set volume.
138  * @core:                       A pointer to the device struct.
139  * @volume:                     The new volume value.
140  */
141 static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume)
142 {
143         int r;
144
145         if (volume > WL1273_MAX_VOLUME)
146                 return -EINVAL;
147
148         if (core->volume == volume)
149                 return 0;
150
151         r = wl1273_fm_write_cmd(core, WL1273_VOLUME_SET, volume);
152         if (r)
153                 return r;
154
155         core->volume = volume;
156         return 0;
157 }
158
159 static int wl1273_core_probe(struct i2c_client *client,
160                                        const struct i2c_device_id *id)
161 {
162         struct wl1273_fm_platform_data *pdata = dev_get_platdata(&client->dev);
163         struct wl1273_core *core;
164         struct mfd_cell *cell;
165         int children = 0;
166         int r = 0;
167
168         dev_dbg(&client->dev, "%s\n", __func__);
169
170         if (!pdata) {
171                 dev_err(&client->dev, "No platform data.\n");
172                 return -EINVAL;
173         }
174
175         if (!(pdata->children & WL1273_RADIO_CHILD)) {
176                 dev_err(&client->dev, "Cannot function without radio child.\n");
177                 return -EINVAL;
178         }
179
180         core = devm_kzalloc(&client->dev, sizeof(*core), GFP_KERNEL);
181         if (!core)
182                 return -ENOMEM;
183
184         core->pdata = pdata;
185         core->client = client;
186         mutex_init(&core->lock);
187
188         i2c_set_clientdata(client, core);
189
190         dev_dbg(&client->dev, "%s: Have V4L2.\n", __func__);
191
192         cell = &core->cells[children];
193         cell->name = "wl1273_fm_radio";
194         cell->platform_data = &core;
195         cell->pdata_size = sizeof(core);
196         children++;
197
198         core->read = wl1273_fm_read_reg;
199         core->write = wl1273_fm_write_cmd;
200         core->write_data = wl1273_fm_write_data;
201         core->set_audio = wl1273_fm_set_audio;
202         core->set_volume = wl1273_fm_set_volume;
203
204         if (pdata->children & WL1273_CODEC_CHILD) {
205                 cell = &core->cells[children];
206
207                 dev_dbg(&client->dev, "%s: Have codec.\n", __func__);
208                 cell->name = "wl1273-codec";
209                 cell->platform_data = &core;
210                 cell->pdata_size = sizeof(core);
211                 children++;
212         }
213
214         dev_dbg(&client->dev, "%s: number of children: %d.\n",
215                 __func__, children);
216
217         r = devm_mfd_add_devices(&client->dev, -1, core->cells,
218                                  children, NULL, 0, NULL);
219         if (r)
220                 goto err;
221
222         return 0;
223
224 err:
225         pdata->free_resources();
226
227         dev_dbg(&client->dev, "%s\n", __func__);
228
229         return r;
230 }
231
232 static struct i2c_driver wl1273_core_driver = {
233         .driver = {
234                 .name = WL1273_FM_DRIVER_NAME,
235         },
236         .probe = wl1273_core_probe,
237         .id_table = wl1273_driver_id_table,
238 };
239
240 static int __init wl1273_core_init(void)
241 {
242         int r;
243
244         r = i2c_add_driver(&wl1273_core_driver);
245         if (r) {
246                 pr_err(WL1273_FM_DRIVER_NAME
247                        ": driver registration failed\n");
248                 return r;
249         }
250
251         return r;
252 }
253
254 static void __exit wl1273_core_exit(void)
255 {
256         i2c_del_driver(&wl1273_core_driver);
257 }
258 late_initcall(wl1273_core_init);
259 module_exit(wl1273_core_exit);
260
261 MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
262 MODULE_DESCRIPTION(DRIVER_DESC);
263 MODULE_LICENSE("GPL");