summaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/audio_module.c
diff options
context:
space:
mode:
authorVaibhav Agarwal <vaibhav.agarwal@linaro.org>2016-03-29 16:32:36 +0530
committerGreg Kroah-Hartman <gregkh@google.com>2016-03-31 10:19:57 -0700
commit64a7e2cceb75ccabaec713944a95511605751b29 (patch)
tree1c745b4cb31d73c8acb1c3ac2eda3b087195142f /drivers/staging/greybus/audio_module.c
parent6da549ec851117293a07e64f97170f7dc9d55578 (diff)
downloadlinux-64a7e2cceb75ccabaec713944a95511605751b29.tar.bz2
greybus: audio: Added jack support to audio module
Register jack with ASoC sound card in case audio module populates it via codec FW. Currently, only a single jack with 4 buttons can be registered for each module. Signed-off-by: Vaibhav Agarwal <vaibhav.agarwal@linaro.org> Reviewed-by: Mark Greer <mgreer@animalcreek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/audio_module.c')
-rw-r--r--drivers/staging/greybus/audio_module.c142
1 files changed, 137 insertions, 5 deletions
diff --git a/drivers/staging/greybus/audio_module.c b/drivers/staging/greybus/audio_module.c
index 94fdadc67c18..9039aa63e040 100644
--- a/drivers/staging/greybus/audio_module.c
+++ b/drivers/staging/greybus/audio_module.c
@@ -22,18 +22,150 @@ static LIST_HEAD(gb_codec_list);
* gb_snd management functions
*/
-static int gbaudio_codec_request_handler(struct gb_operation *op)
+static int gbaudio_request_jack(struct gbaudio_module_info *module,
+ struct gb_audio_jack_event_request *req)
{
- struct gb_connection *connection = op->connection;
- struct gb_audio_streaming_event_request *req = op->request->payload;
+ int report, button_status;
+
+ dev_warn(module->dev, "Jack Event received: type: %u, event: %u\n",
+ req->widget_type, req->event);
+
+ mutex_lock(&module->lock);
+ if (req->event == GB_AUDIO_JACK_EVENT_REMOVAL) {
+ module->jack_type = 0;
+ button_status = module->button_status;
+ module->button_status = 0;
+ mutex_unlock(&module->lock);
+ if (button_status)
+ snd_soc_jack_report(&module->button_jack, 0,
+ GBCODEC_JACK_BUTTON_MASK);
+ snd_soc_jack_report(&module->headset_jack, 0,
+ GBCODEC_JACK_MASK);
+ return 0;
+ }
+
+ report &= ~GBCODEC_JACK_MASK;
+ /* currently supports Headphone, Headset & Lineout only */
+ if (req->widget_type && GB_AUDIO_WIDGET_TYPE_HP)
+ report |= SND_JACK_HEADPHONE & GBCODEC_JACK_MASK;
+
+ if (req->widget_type && GB_AUDIO_WIDGET_TYPE_MIC)
+ report = SND_JACK_MICROPHONE & GBCODEC_JACK_MASK;
+
+ if (req->widget_type && GB_AUDIO_WIDGET_TYPE_LINE)
+ report = (report & GBCODEC_JACK_MASK) |
+ SND_JACK_LINEOUT | SND_JACK_LINEIN;
+
+ if (module->jack_type)
+ dev_warn(module->dev, "Modifying jack from %d to %d\n",
+ module->jack_type, report);
+
+ module->jack_type = report;
+ mutex_unlock(&module->lock);
+ snd_soc_jack_report(&module->headset_jack, report, GBCODEC_JACK_MASK);
+
+ return 0;
+}
+
+static int gbaudio_request_button(struct gbaudio_module_info *module,
+ struct gb_audio_button_event_request *req)
+{
+ int soc_button_id, report;
+
+ dev_warn(module->dev, "Button Event received: id: %u, event: %u\n",
+ req->button_id, req->event);
+
+ /* currently supports 4 buttons only */
+ mutex_lock(&module->lock);
+ if (!module->jack_type) {
+ dev_err(module->dev, "Jack not present. Bogus event!!\n");
+ mutex_unlock(&module->lock);
+ return -EINVAL;
+ }
+
+ report = module->button_status & GBCODEC_JACK_BUTTON_MASK;
+
+ switch (req->button_id) {
+ case 1:
+ soc_button_id = SND_JACK_BTN_0;
+ break;
+
+ case 2:
+ soc_button_id = SND_JACK_BTN_1;
+ break;
- dev_warn(&connection->bundle->dev,
- "Audio Event received: cport: %u, event: %u\n",
+ case 3:
+ soc_button_id = SND_JACK_BTN_2;
+ break;
+
+ case 4:
+ soc_button_id = SND_JACK_BTN_3;
+ break;
+ default:
+ dev_err(module->dev, "Invalid button request received\n");
+ return -EINVAL;
+ }
+
+ if (req->event == GB_AUDIO_BUTTON_EVENT_PRESS)
+ report = report | soc_button_id;
+ else
+ report = report & ~soc_button_id;
+
+ module->button_status = report;
+
+ mutex_unlock(&module->lock);
+
+ snd_soc_jack_report(&module->button_jack, report,
+ GBCODEC_JACK_BUTTON_MASK);
+
+ return 0;
+}
+
+static int gbaudio_request_stream(struct gbaudio_module_info *module,
+ struct gb_audio_streaming_event_request *req)
+{
+ dev_warn(module->dev, "Audio Event received: cport: %u, event: %u\n",
req->data_cport, req->event);
return 0;
}
+static int gbaudio_codec_request_handler(struct gb_operation *op)
+{
+ struct gb_connection *connection = op->connection;
+ struct gbaudio_module_info *module =
+ greybus_get_drvdata(connection->bundle);
+ struct gb_operation_msg_hdr *header = op->request->header;
+ struct gb_audio_streaming_event_request *stream_req;
+ struct gb_audio_jack_event_request *jack_req;
+ struct gb_audio_button_event_request *button_req;
+ int ret;
+
+ switch (header->type) {
+ case GB_AUDIO_TYPE_STREAMING_EVENT:
+ stream_req = op->request->payload;
+ ret = gbaudio_request_stream(module, stream_req);
+ break;
+
+ case GB_AUDIO_TYPE_JACK_EVENT:
+ jack_req = op->request->payload;
+ ret = gbaudio_request_jack(module, jack_req);
+ break;
+
+ case GB_AUDIO_TYPE_BUTTON_EVENT:
+ button_req = op->request->payload;
+ ret = gbaudio_request_button(module, button_req);
+ break;
+
+ default:
+ dev_err(&connection->bundle->dev,
+ "Invalid Audio Event received\n");
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
static int gbaudio_data_connection_request_handler(struct gb_operation *op)
{
struct gb_connection *connection = op->connection;