summaryrefslogtreecommitdiffstats
path: root/include/sound/hwdep.h
blob: ab9fcb2f97f0abfbb1307138eec19e7f0dbe6a39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#ifndef __SOUND_HWDEP_H
#define __SOUND_HWDEP_H

/*
 *  Hardware dependent layer 
 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
 *
 *
 *   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 <sound/asound.h>
#include <linux/poll.h>

struct snd_hwdep;

/* hwdep file ops; all ops can be NULL */
struct snd_hwdep_ops {
	long long (*llseek)(struct snd_hwdep *hw, struct file *file,
			    long long offset, int orig);
	long (*read)(struct snd_hwdep *hw, char __user *buf,
		     long count, loff_t *offset);
	long (*write)(struct snd_hwdep *hw, const char __user *buf,
		      long count, loff_t *offset);
	int (*open)(struct snd_hwdep *hw, struct file * file);
	int (*release)(struct snd_hwdep *hw, struct file * file);
	unsigned int (*poll)(struct snd_hwdep *hw, struct file *file,
			     poll_table *wait);
	int (*ioctl)(struct snd_hwdep *hw, struct file *file,
		     unsigned int cmd, unsigned long arg);
	int (*ioctl_compat)(struct snd_hwdep *hw, struct file *file,
			    unsigned int cmd, unsigned long arg);
	int (*mmap)(struct snd_hwdep *hw, struct file *file,
		    struct vm_area_struct *vma);
	int (*dsp_status)(struct snd_hwdep *hw,
			  struct snd_hwdep_dsp_status *status);
	int (*dsp_load)(struct snd_hwdep *hw,
			struct snd_hwdep_dsp_image *image);
};

struct snd_hwdep {
	struct snd_card *card;
	struct list_head list;
	int device;
	char id[32];
	char name[80];
	int iface;

#ifdef CONFIG_SND_OSSEMUL
	int oss_type;
	int ossreg;
#endif

	struct snd_hwdep_ops ops;
	wait_queue_head_t open_wait;
	void *private_data;
	void (*private_free) (struct snd_hwdep *hwdep);
	struct device dev;

	struct mutex open_mutex;
	int used;			/* reference counter */
	unsigned int dsp_loaded;	/* bit fields of loaded dsp indices */
	unsigned int exclusive:1;	/* exclusive access mode */
};

extern int snd_hwdep_new(struct snd_card *card, char *id, int device,
			 struct snd_hwdep **rhwdep);

#endif /* __SOUND_HWDEP_H */
ss="w"> export->pwm; } static ssize_t period_show(struct device *child, struct device_attribute *attr, char *buf) { const struct pwm_device *pwm = child_to_pwm_device(child); struct pwm_state state; pwm_get_state(pwm, &state); return sprintf(buf, "%u\n", state.period); } static ssize_t period_store(struct device *child, struct device_attribute *attr, const char *buf, size_t size) { struct pwm_export *export = child_to_pwm_export(child); struct pwm_device *pwm = export->pwm; struct pwm_state state; unsigned int val; int ret; ret = kstrtouint(buf, 0, &val); if (ret) return ret; mutex_lock(&export->lock); pwm_get_state(pwm, &state); state.period = val; ret = pwm_apply_state(pwm, &state); mutex_unlock(&export->lock); return ret ? : size; } static ssize_t duty_cycle_show(struct device *child, struct device_attribute *attr, char *buf) { const struct pwm_device *pwm = child_to_pwm_device(child); struct pwm_state state; pwm_get_state(pwm, &state); return sprintf(buf, "%u\n", state.duty_cycle); } static ssize_t duty_cycle_store(struct device *child, struct device_attribute *attr, const char *buf, size_t size) { struct pwm_export *export = child_to_pwm_export(child); struct pwm_device *pwm = export->pwm; struct pwm_state state; unsigned int val; int ret; ret = kstrtouint(buf, 0, &val); if (ret) return ret; mutex_lock(&export->lock); pwm_get_state(pwm, &state); state.duty_cycle = val; ret = pwm_apply_state(pwm, &state); mutex_unlock(&export->lock); return ret ? : size; } static ssize_t enable_show(struct device *child, struct device_attribute *attr, char *buf) { const struct pwm_device *pwm = child_to_pwm_device(child); struct pwm_state state; pwm_get_state(pwm, &state); return sprintf(buf, "%d\n", state.enabled); } static ssize_t enable_store(struct device *child, struct device_attribute *attr, const char *buf, size_t size) { struct pwm_export *export = child_to_pwm_export(child); struct pwm_device *pwm = export->pwm; struct pwm_state state; int val, ret; ret = kstrtoint(buf, 0, &val); if (ret) return ret; mutex_lock(&export->lock); pwm_get_state(pwm, &state); switch (val) { case 0: state.enabled = false; break; case 1: state.enabled = true; break; default: ret = -EINVAL; goto unlock; } ret = pwm_apply_state(pwm, &state); unlock: mutex_unlock(&export->lock); return ret ? : size; } static ssize_t polarity_show(struct device *child, struct device_attribute *attr, char *buf) { const struct pwm_device *pwm = child_to_pwm_device(child); const char *polarity = "unknown"; struct pwm_state state; pwm_get_state(pwm, &state); switch (state.polarity) { case PWM_POLARITY_NORMAL: polarity = "normal"; break; case PWM_POLARITY_INVERSED: polarity = "inversed"; break; } return sprintf(buf, "%s\n", polarity); } static ssize_t polarity_store(struct device *child, struct device_attribute *attr, const char *buf, size_t size) { struct pwm_export *export = child_to_pwm_export(child); struct pwm_device *pwm = export->pwm; enum pwm_polarity polarity; struct pwm_state state; int ret; if (sysfs_streq(buf, "normal")) polarity = PWM_POLARITY_NORMAL; else if (sysfs_streq(buf, "inversed")) polarity = PWM_POLARITY_INVERSED; else return -EINVAL; mutex_lock(&export->lock); pwm_get_state(pwm, &state); state.polarity = polarity; ret = pwm_apply_state(pwm, &state); mutex_unlock(&export->lock); return ret ? : size; } static ssize_t capture_show(struct device *child, struct device_attribute *attr, char *buf) { struct pwm_device *pwm = child_to_pwm_device(child); struct pwm_capture result; int ret; ret = pwm_capture(pwm, &result, jiffies_to_msecs(HZ)); if (ret) return ret; return sprintf(buf, "%u %u\n", result.period, result.duty_cycle); } static DEVICE_ATTR_RW(period); static DEVICE_ATTR_RW(duty_cycle); static DEVICE_ATTR_RW(enable); static DEVICE_ATTR_RW(polarity); static DEVICE_ATTR_RO(capture); static struct attribute *pwm_attrs[] = { &dev_attr_period.attr, &dev_attr_duty_cycle.attr, &dev_attr_enable.attr, &dev_attr_polarity.attr, &dev_attr_capture.attr, NULL }; ATTRIBUTE_GROUPS(pwm); static void pwm_export_release(struct device *child) { struct pwm_export *export = child_to_pwm_export(child); kfree(export); } static int pwm_export_child(struct device *parent, struct pwm_device *pwm) { struct pwm_export *export; char *pwm_prop[2]; int ret; if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags)) return -EBUSY; export = kzalloc(sizeof(*export), GFP_KERNEL); if (!export) { clear_bit(PWMF_EXPORTED, &pwm->flags); return -ENOMEM; } export->pwm = pwm; mutex_init(&export->lock); export->child.release = pwm_export_release; export->