cregit-Linux how code gets into the kernel

Release 4.11 drivers/media/pci/cx18/cx18-alsa-mixer.c

/*
 *  ALSA mixer controls for the
 *  ALSA interface to cx18 PCM capture streams
 *
 *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/spinlock.h>
#include <linux/videodev2.h>

#include <media/v4l2-device.h>

#include <sound/core.h>
#include <sound/control.h>
#include <sound/tlv.h>

#include "cx18-alsa.h"
#include "cx18-driver.h"

/*
 * Note the cx18-av-core volume scale is funny, due to the alignment of the
 * scale with another chip's range:
 *
 * v4l2_control value   /512    indicated dB    actual dB       reg 0x8d4
 * 0x0000 - 0x01ff        0     -119            -96             228
 * 0x0200 - 0x02ff        1     -118            -96             228
 * ...
 * 0x2c00 - 0x2dff       22      -97            -96             228
 * 0x2e00 - 0x2fff       23      -96            -96             228
 * 0x3000 - 0x31ff       24      -95            -95             226
 * ...
 * 0xee00 - 0xefff      119        0              0              36
 * ...
 * 0xfe00 - 0xffff      127       +8             +8              20
 */

static inline int dB_to_cx18_av_vol(int dB) { if (dB < -96) dB = -96; else if (dB > 8) dB = 8; return (dB + 119) << 9; }

Contributors

PersonTokensPropCommitsCommitProp
Andy Walls42100.00%1100.00%
Total42100.00%1100.00%


static inline int cx18_av_vol_to_dB(int v) { if (v < (23 << 9)) v = (23 << 9); else if (v > (127 << 9)) v = (127 << 9); return (v >> 9) - 119; }

Contributors

PersonTokensPropCommitsCommitProp
Andy Walls56100.00%1100.00%
Total56100.00%1100.00%


static int snd_cx18_mixer_tv_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; /* We're already translating values, just keep this control in dB */ uinfo->value.integer.min = -96; uinfo->value.integer.max = 8; uinfo->value.integer.step = 1; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Andy Walls63100.00%1100.00%
Total63100.00%1100.00%


static int snd_cx18_mixer_tv_vol_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) { struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl); struct cx18 *cx = to_cx18(cxsc->v4l2_dev); struct v4l2_control vctrl; int ret; vctrl.id = V4L2_CID_AUDIO_VOLUME; vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]); snd_cx18_lock(cxsc); ret = v4l2_g_ctrl(cx->sd_av->ctrl_handler, &vctrl); snd_cx18_unlock(cxsc); if (!ret) uctl->value.integer.value[0] = cx18_av_vol_to_dB(vctrl.value); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Andy Walls11697.48%266.67%
Hans Verkuil32.52%133.33%
Total119100.00%3100.00%


static int snd_cx18_mixer_tv_vol_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) { struct snd_cx18_card *cxsc = snd_kcontrol_chip(kctl); struct cx18 *cx = to_cx18(cxsc->v4l2_dev); struct v4l2_control vctrl; int ret; vctrl.id = V4L2_CID_AUDIO_VOLUME; vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]); snd_cx18_lock(cxsc); /* Fetch current state */ ret = v4l2_g_ctrl(cx->sd_av->ctrl_handler, &vctrl); if (ret || (cx18_av_vol_to_dB(vctrl.value) != uctl->value.integer.value[0])) { /* Set, if needed */ vctrl.value = dB_to_cx18_av_vol(uctl->value.integer.value[0]); ret = v4l2_s_ctrl(cx->sd_av->ctrl_handler, &vctrl); if (!ret) ret = 1; /* Indicate control was changed w/o error */ } snd_cx18_unlock(cxsc); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Andy Walls16096.39%266.67%
Hans Verkuil63.61%133.33%
Total166100.00%3100.00%

/* This is a bit of overkill, the slider is already in dB internally */ static DECLARE_TLV_DB_SCALE(snd_cx18_mixer_tv_vol_db_scale, -9600, 100, 0); static struct snd_kcontrol_new snd_cx18_mixer_tv_vol __initdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Analog TV Capture Volume", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, .info = snd_cx18_mixer_tv_volume_info, .get = snd_cx18_mixer_tv_volume_get, .put = snd_cx18_mixer_tv_volume_put, .tlv.p = snd_cx18_mixer_tv_vol_db_scale }; /* FIXME - add mute switch and balance, bass, treble sliders: V4L2_CID_AUDIO_MUTE V4L2_CID_AUDIO_BALANCE V4L2_CID_AUDIO_BASS V4L2_CID_AUDIO_TREBLE */ /* FIXME - add stereo, lang1, lang2, mono menu */ /* FIXME - add CS5345 I2S volume for HVR-1600 */
int __init snd_cx18_mixer_create(struct snd_cx18_card *cxsc) { struct v4l2_device *v4l2_dev = cxsc->v4l2_dev; struct snd_card *sc = cxsc->sc; int ret; strlcpy(sc->mixername, "CX23418 Mixer", sizeof(sc->mixername)); ret = snd_ctl_add(sc, snd_ctl_new1(snd_cx18_mixer_tv_vol, cxsc)); if (ret) { CX18_ALSA_WARN("%s: failed to add %s control, err %d\n", __func__, snd_cx18_mixer_tv_vol.name, ret); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Andy Walls84100.00%1100.00%
Total84100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Andy Walls61998.41%250.00%
Hans Verkuil91.43%125.00%
Sakari Ailus10.16%125.00%
Total629100.00%4100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.