cregit-Linux how code gets into the kernel

Release 4.7 drivers/media/pci/ivtv/ivtv-alsa-mixer.c

/*
 *  ALSA mixer controls for the
 *  ALSA interface to ivtv PCM capture streams
 *
 *  Copyright (C) 2009,2012  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.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307  USA
 */

#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 "ivtv-alsa.h"
#include "ivtv-driver.h"

/*
 * Note the cx25840-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_cx25840_vol(int dB) { if (dB < -96) dB = -96; else if (dB > 8) dB = 8; return (dB + 119) << 9; }

Contributors

PersonTokensPropCommitsCommitProp
andy wallsandy walls42100.00%1100.00%
Total42100.00%1100.00%


static inline int cx25840_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 wallsandy walls56100.00%1100.00%
Total56100.00%1100.00%


static int snd_ivtv_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 wallsandy walls63100.00%1100.00%
Total63100.00%1100.00%


static int snd_ivtv_mixer_tv_vol_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) { struct snd_ivtv_card *itvsc = snd_kcontrol_chip(kctl); struct ivtv *itv = to_ivtv(itvsc->v4l2_dev); struct v4l2_control vctrl; int ret; vctrl.id = V4L2_CID_AUDIO_VOLUME; vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]); snd_ivtv_lock(itvsc); ret = v4l2_subdev_call(itv->sd_audio, core, g_ctrl, &vctrl); snd_ivtv_unlock(itvsc); if (!ret) uctl->value.integer.value[0] = cx25840_vol_to_dB(vctrl.value); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
andy wallsandy walls121100.00%1100.00%
Total121100.00%1100.00%


static int snd_ivtv_mixer_tv_vol_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *uctl) { struct snd_ivtv_card *itvsc = snd_kcontrol_chip(kctl); struct ivtv *itv = to_ivtv(itvsc->v4l2_dev); struct v4l2_control vctrl; int ret; vctrl.id = V4L2_CID_AUDIO_VOLUME; vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]); snd_ivtv_lock(itvsc); /* Fetch current state */ ret = v4l2_subdev_call(itv->sd_audio, core, g_ctrl, &vctrl); if (ret || (cx25840_vol_to_dB(vctrl.value) != uctl->value.integer.value[0])) { /* Set, if needed */ vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]); ret = v4l2_subdev_call(itv->sd_audio, core, s_ctrl, &vctrl); if (!ret) ret = 1; /* Indicate control was changed w/o error */ } snd_ivtv_unlock(itvsc); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
andy wallsandy walls170100.00%1100.00%
Total170100.00%1100.00%

/* This is a bit of overkill, the slider is already in dB internally */ static DECLARE_TLV_DB_SCALE(snd_ivtv_mixer_tv_vol_db_scale, -9600, 100, 0); static struct snd_kcontrol_new snd_ivtv_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_ivtv_mixer_tv_volume_info, .get = snd_ivtv_mixer_tv_volume_get, .put = snd_ivtv_mixer_tv_volume_put, .tlv.p = snd_ivtv_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 I2S volume */
int __init snd_ivtv_mixer_create(struct snd_ivtv_card *itvsc) { struct v4l2_device *v4l2_dev = itvsc->v4l2_dev; struct snd_card *sc = itvsc->sc; int ret; strlcpy(sc->mixername, "CX2341[56] Mixer", sizeof(sc->mixername)); ret = snd_ctl_add(sc, snd_ctl_new1(snd_ivtv_mixer_tv_vol, itvsc)); if (ret) { IVTV_ALSA_WARN("%s: failed to add %s control, err %d\n", __func__, snd_ivtv_mixer_tv_vol.name, ret); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
andy wallsandy walls84100.00%1100.00%
Total84100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
andy wallsandy walls635100.00%1100.00%
Total635100.00%1100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}