diff options
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rw-r--r-- | arch/x86/pci/common.c | 8 | ||||
-rw-r--r-- | drivers/firewire/fw-cdev.c | 14 | ||||
-rw-r--r-- | drivers/ieee1394/sbp2.c | 20 | ||||
-rw-r--r-- | drivers/media/video/bt8xx/bttv-driver.c | 2 | ||||
-rw-r--r-- | drivers/media/video/videobuf-core.c | 3 | ||||
-rw-r--r-- | include/media/videobuf-core.h | 3 | ||||
-rw-r--r-- | sound/drivers/pcsp/pcsp.c | 2 | ||||
-rw-r--r-- | sound/drivers/pcsp/pcsp_lib.c | 37 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 48 |
10 files changed, 67 insertions, 72 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 7fd9c430aea4..b42dcfcbee44 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3145,7 +3145,7 @@ PCI ERROR RECOVERY | |||
3145 | P: Linas Vepstas | 3145 | P: Linas Vepstas |
3146 | M: linas@austin.ibm.com | 3146 | M: linas@austin.ibm.com |
3147 | L: linux-kernel@vger.kernel.org | 3147 | L: linux-kernel@vger.kernel.org |
3148 | L: linux-pci@atrey.karlin.mff.cuni.cz | 3148 | L: linux-pci@vger.kernel.org |
3149 | S: Supported | 3149 | S: Supported |
3150 | 3150 | ||
3151 | PCI SUBSYSTEM | 3151 | PCI SUBSYSTEM |
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 8545c8a9d107..6e64aaf00d1d 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c | |||
@@ -302,18 +302,18 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { | |||
302 | }, | 302 | }, |
303 | { | 303 | { |
304 | .callback = set_bf_sort, | 304 | .callback = set_bf_sort, |
305 | .ident = "HP ProLiant DL385 G2", | 305 | .ident = "HP ProLiant DL360", |
306 | .matches = { | 306 | .matches = { |
307 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | 307 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), |
308 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385 G2"), | 308 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL360"), |
309 | }, | 309 | }, |
310 | }, | 310 | }, |
311 | { | 311 | { |
312 | .callback = set_bf_sort, | 312 | .callback = set_bf_sort, |
313 | .ident = "HP ProLiant DL585 G2", | 313 | .ident = "HP ProLiant DL380", |
314 | .matches = { | 314 | .matches = { |
315 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | 315 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), |
316 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"), | 316 | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL380"), |
317 | }, | 317 | }, |
318 | }, | 318 | }, |
319 | #ifdef __i386__ | 319 | #ifdef __i386__ |
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 4a541921a14a..dda14015e873 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c | |||
@@ -113,6 +113,11 @@ static int fw_device_op_open(struct inode *inode, struct file *file) | |||
113 | if (device == NULL) | 113 | if (device == NULL) |
114 | return -ENODEV; | 114 | return -ENODEV; |
115 | 115 | ||
116 | if (fw_device_is_shutdown(device)) { | ||
117 | fw_device_put(device); | ||
118 | return -ENODEV; | ||
119 | } | ||
120 | |||
116 | client = kzalloc(sizeof(*client), GFP_KERNEL); | 121 | client = kzalloc(sizeof(*client), GFP_KERNEL); |
117 | if (client == NULL) { | 122 | if (client == NULL) { |
118 | fw_device_put(device); | 123 | fw_device_put(device); |
@@ -901,6 +906,9 @@ fw_device_op_ioctl(struct file *file, | |||
901 | { | 906 | { |
902 | struct client *client = file->private_data; | 907 | struct client *client = file->private_data; |
903 | 908 | ||
909 | if (fw_device_is_shutdown(client->device)) | ||
910 | return -ENODEV; | ||
911 | |||
904 | return dispatch_ioctl(client, cmd, (void __user *) arg); | 912 | return dispatch_ioctl(client, cmd, (void __user *) arg); |
905 | } | 913 | } |
906 | 914 | ||
@@ -911,6 +919,9 @@ fw_device_op_compat_ioctl(struct file *file, | |||
911 | { | 919 | { |
912 | struct client *client = file->private_data; | 920 | struct client *client = file->private_data; |
913 | 921 | ||
922 | if (fw_device_is_shutdown(client->device)) | ||
923 | return -ENODEV; | ||
924 | |||
914 | return dispatch_ioctl(client, cmd, compat_ptr(arg)); | 925 | return dispatch_ioctl(client, cmd, compat_ptr(arg)); |
915 | } | 926 | } |
916 | #endif | 927 | #endif |
@@ -922,6 +933,9 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) | |||
922 | unsigned long size; | 933 | unsigned long size; |
923 | int page_count, retval; | 934 | int page_count, retval; |
924 | 935 | ||
936 | if (fw_device_is_shutdown(client->device)) | ||
937 | return -ENODEV; | ||
938 | |||
925 | /* FIXME: We could support multiple buffers, but we don't. */ | 939 | /* FIXME: We could support multiple buffers, but we don't. */ |
926 | if (client->buffer.pages != NULL) | 940 | if (client->buffer.pages != NULL) |
927 | return -EBUSY; | 941 | return -EBUSY; |
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 16b9d0ad154e..a5ceff287a28 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
@@ -1539,15 +1539,13 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb, | |||
1539 | 1539 | ||
1540 | static void sbp2_create_command_orb(struct sbp2_lu *lu, | 1540 | static void sbp2_create_command_orb(struct sbp2_lu *lu, |
1541 | struct sbp2_command_info *cmd, | 1541 | struct sbp2_command_info *cmd, |
1542 | unchar *scsi_cmd, | 1542 | struct scsi_cmnd *SCpnt) |
1543 | unsigned int scsi_use_sg, | ||
1544 | unsigned int scsi_request_bufflen, | ||
1545 | struct scatterlist *sg, | ||
1546 | enum dma_data_direction dma_dir) | ||
1547 | { | 1543 | { |
1548 | struct sbp2_fwhost_info *hi = lu->hi; | 1544 | struct sbp2_fwhost_info *hi = lu->hi; |
1549 | struct sbp2_command_orb *orb = &cmd->command_orb; | 1545 | struct sbp2_command_orb *orb = &cmd->command_orb; |
1550 | u32 orb_direction; | 1546 | u32 orb_direction; |
1547 | unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt); | ||
1548 | enum dma_data_direction dma_dir = SCpnt->sc_data_direction; | ||
1551 | 1549 | ||
1552 | /* | 1550 | /* |
1553 | * Set-up our command ORB. | 1551 | * Set-up our command ORB. |
@@ -1580,13 +1578,14 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu, | |||
1580 | orb->data_descriptor_lo = 0x0; | 1578 | orb->data_descriptor_lo = 0x0; |
1581 | orb->misc |= ORB_SET_DIRECTION(1); | 1579 | orb->misc |= ORB_SET_DIRECTION(1); |
1582 | } else | 1580 | } else |
1583 | sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sg, | 1581 | sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_sg_count(SCpnt), |
1582 | scsi_sglist(SCpnt), | ||
1584 | orb_direction, dma_dir); | 1583 | orb_direction, dma_dir); |
1585 | 1584 | ||
1586 | sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb)); | 1585 | sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb)); |
1587 | 1586 | ||
1588 | memset(orb->cdb, 0, 12); | 1587 | memset(orb->cdb, 0, sizeof(orb->cdb)); |
1589 | memcpy(orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd)); | 1588 | memcpy(orb->cdb, SCpnt->cmnd, SCpnt->cmd_len); |
1590 | } | 1589 | } |
1591 | 1590 | ||
1592 | static void sbp2_link_orb_command(struct sbp2_lu *lu, | 1591 | static void sbp2_link_orb_command(struct sbp2_lu *lu, |
@@ -1669,16 +1668,13 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu, | |||
1669 | static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt, | 1668 | static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt, |
1670 | void (*done)(struct scsi_cmnd *)) | 1669 | void (*done)(struct scsi_cmnd *)) |
1671 | { | 1670 | { |
1672 | unchar *scsi_cmd = (unchar *)SCpnt->cmnd; | ||
1673 | struct sbp2_command_info *cmd; | 1671 | struct sbp2_command_info *cmd; |
1674 | 1672 | ||
1675 | cmd = sbp2util_allocate_command_orb(lu, SCpnt, done); | 1673 | cmd = sbp2util_allocate_command_orb(lu, SCpnt, done); |
1676 | if (!cmd) | 1674 | if (!cmd) |
1677 | return -EIO; | 1675 | return -EIO; |
1678 | 1676 | ||
1679 | sbp2_create_command_orb(lu, cmd, scsi_cmd, scsi_sg_count(SCpnt), | 1677 | sbp2_create_command_orb(lu, cmd, SCpnt); |
1680 | scsi_bufflen(SCpnt), scsi_sglist(SCpnt), | ||
1681 | SCpnt->sc_data_direction); | ||
1682 | sbp2_link_orb_command(lu, cmd); | 1678 | sbp2_link_orb_command(lu, cmd); |
1683 | 1679 | ||
1684 | return 0; | 1680 | return 0; |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 2ca3e9cfb2bb..0165aac533bf 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -2613,7 +2613,7 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf) | |||
2613 | struct bttv_fh *fh = priv; | 2613 | struct bttv_fh *fh = priv; |
2614 | 2614 | ||
2615 | mutex_lock(&fh->cap.vb_lock); | 2615 | mutex_lock(&fh->cap.vb_lock); |
2616 | retval = videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize, | 2616 | retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize, |
2617 | V4L2_MEMORY_MMAP); | 2617 | V4L2_MEMORY_MMAP); |
2618 | if (retval < 0) { | 2618 | if (retval < 0) { |
2619 | mutex_unlock(&fh->cap.vb_lock); | 2619 | mutex_unlock(&fh->cap.vb_lock); |
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c index 982f4463896c..0a88c44ace00 100644 --- a/drivers/media/video/videobuf-core.c +++ b/drivers/media/video/videobuf-core.c | |||
@@ -331,7 +331,7 @@ int videobuf_mmap_free(struct videobuf_queue *q) | |||
331 | } | 331 | } |
332 | 332 | ||
333 | /* Locking: Caller holds q->vb_lock */ | 333 | /* Locking: Caller holds q->vb_lock */ |
334 | static int __videobuf_mmap_setup(struct videobuf_queue *q, | 334 | int __videobuf_mmap_setup(struct videobuf_queue *q, |
335 | unsigned int bcount, unsigned int bsize, | 335 | unsigned int bcount, unsigned int bsize, |
336 | enum v4l2_memory memory) | 336 | enum v4l2_memory memory) |
337 | { | 337 | { |
@@ -1129,6 +1129,7 @@ EXPORT_SYMBOL_GPL(videobuf_read_stream); | |||
1129 | EXPORT_SYMBOL_GPL(videobuf_read_one); | 1129 | EXPORT_SYMBOL_GPL(videobuf_read_one); |
1130 | EXPORT_SYMBOL_GPL(videobuf_poll_stream); | 1130 | EXPORT_SYMBOL_GPL(videobuf_poll_stream); |
1131 | 1131 | ||
1132 | EXPORT_SYMBOL_GPL(__videobuf_mmap_setup); | ||
1132 | EXPORT_SYMBOL_GPL(videobuf_mmap_setup); | 1133 | EXPORT_SYMBOL_GPL(videobuf_mmap_setup); |
1133 | EXPORT_SYMBOL_GPL(videobuf_mmap_free); | 1134 | EXPORT_SYMBOL_GPL(videobuf_mmap_free); |
1134 | EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); | 1135 | EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); |
diff --git a/include/media/videobuf-core.h b/include/media/videobuf-core.h index 5b39a22533fe..874f1340d049 100644 --- a/include/media/videobuf-core.h +++ b/include/media/videobuf-core.h | |||
@@ -237,6 +237,9 @@ unsigned int videobuf_poll_stream(struct file *file, | |||
237 | int videobuf_mmap_setup(struct videobuf_queue *q, | 237 | int videobuf_mmap_setup(struct videobuf_queue *q, |
238 | unsigned int bcount, unsigned int bsize, | 238 | unsigned int bcount, unsigned int bsize, |
239 | enum v4l2_memory memory); | 239 | enum v4l2_memory memory); |
240 | int __videobuf_mmap_setup(struct videobuf_queue *q, | ||
241 | unsigned int bcount, unsigned int bsize, | ||
242 | enum v4l2_memory memory); | ||
240 | int videobuf_mmap_free(struct videobuf_queue *q); | 243 | int videobuf_mmap_free(struct videobuf_queue *q); |
241 | int videobuf_mmap_mapper(struct videobuf_queue *q, | 244 | int videobuf_mmap_mapper(struct videobuf_queue *q, |
242 | struct vm_area_struct *vma); | 245 | struct vm_area_struct *vma); |
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c index 54a1f9036c66..1899cf0685bc 100644 --- a/sound/drivers/pcsp/pcsp.c +++ b/sound/drivers/pcsp/pcsp.c | |||
@@ -96,7 +96,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev) | |||
96 | return -EINVAL; | 96 | return -EINVAL; |
97 | 97 | ||
98 | hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | 98 | hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
99 | pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE; | 99 | pcsp_chip.timer.cb_mode = HRTIMER_CB_SOFTIRQ; |
100 | pcsp_chip.timer.function = pcsp_do_timer; | 100 | pcsp_chip.timer.function = pcsp_do_timer; |
101 | 101 | ||
102 | card = snd_card_new(index, id, THIS_MODULE, 0); | 102 | card = snd_card_new(index, id, THIS_MODULE, 0); |
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index 7ad4a1534b2b..e341f3f83b6a 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/moduleparam.h> | 10 | #include <linux/moduleparam.h> |
11 | #include <sound/pcm.h> | 11 | #include <sound/pcm.h> |
12 | #include <linux/interrupt.h> | ||
13 | #include <asm/io.h> | 12 | #include <asm/io.h> |
14 | #include "pcsp.h" | 13 | #include "pcsp.h" |
15 | 14 | ||
@@ -20,34 +19,8 @@ MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround " | |||
20 | 19 | ||
21 | #define DMIX_WANTS_S16 1 | 20 | #define DMIX_WANTS_S16 1 |
22 | 21 | ||
23 | static void pcsp_start_timer(unsigned long dummy) | ||
24 | { | ||
25 | hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); | ||
26 | } | ||
27 | |||
28 | /* | ||
29 | * We need the hrtimer_start as a tasklet to avoid | ||
30 | * the nasty locking problem. :( | ||
31 | * The problem: | ||
32 | * - The timer handler is called with the cpu_base->lock | ||
33 | * already held by hrtimer code. | ||
34 | * - snd_pcm_period_elapsed() takes the | ||
35 | * substream->self_group.lock. | ||
36 | * So far so good. | ||
37 | * But the snd_pcsp_trigger() is called with the | ||
38 | * substream->self_group.lock held, and it calls | ||
39 | * hrtimer_start(), which takes the cpu_base->lock. | ||
40 | * You see the problem. We have the code pathes | ||
41 | * which take two locks in a reverse order. This | ||
42 | * can deadlock and the lock validator complains. | ||
43 | * The only solution I could find was to move the | ||
44 | * hrtimer_start() into a tasklet. -stsp | ||
45 | */ | ||
46 | static DECLARE_TASKLET(pcsp_start_timer_tasklet, pcsp_start_timer, 0); | ||
47 | |||
48 | enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) | 22 | enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) |
49 | { | 23 | { |
50 | unsigned long flags; | ||
51 | unsigned char timer_cnt, val; | 24 | unsigned char timer_cnt, val; |
52 | int fmt_size, periods_elapsed; | 25 | int fmt_size, periods_elapsed; |
53 | u64 ns; | 26 | u64 ns; |
@@ -66,9 +39,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) | |||
66 | return HRTIMER_RESTART; | 39 | return HRTIMER_RESTART; |
67 | } | 40 | } |
68 | 41 | ||
69 | /* hrtimer calls us from both hardirq and softirq contexts, | 42 | spin_lock_irq(&chip->substream_lock); |
70 | * so irqsave :( */ | ||
71 | spin_lock_irqsave(&chip->substream_lock, flags); | ||
72 | /* Takashi Iwai says regarding this extra lock: | 43 | /* Takashi Iwai says regarding this extra lock: |
73 | 44 | ||
74 | If the irq handler handles some data on the DMA buffer, it should | 45 | If the irq handler handles some data on the DMA buffer, it should |
@@ -139,7 +110,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) | |||
139 | chip->period_ptr %= buffer_bytes; | 110 | chip->period_ptr %= buffer_bytes; |
140 | } | 111 | } |
141 | 112 | ||
142 | spin_unlock_irqrestore(&chip->substream_lock, flags); | 113 | spin_unlock_irq(&chip->substream_lock); |
143 | 114 | ||
144 | if (!atomic_read(&chip->timer_active)) | 115 | if (!atomic_read(&chip->timer_active)) |
145 | return HRTIMER_NORESTART; | 116 | return HRTIMER_NORESTART; |
@@ -153,7 +124,7 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) | |||
153 | exit_nr_unlock2: | 124 | exit_nr_unlock2: |
154 | snd_pcm_stream_unlock(substream); | 125 | snd_pcm_stream_unlock(substream); |
155 | exit_nr_unlock1: | 126 | exit_nr_unlock1: |
156 | spin_unlock_irqrestore(&chip->substream_lock, flags); | 127 | spin_unlock_irq(&chip->substream_lock); |
157 | return HRTIMER_NORESTART; | 128 | return HRTIMER_NORESTART; |
158 | } | 129 | } |
159 | 130 | ||
@@ -174,7 +145,7 @@ static void pcsp_start_playing(struct snd_pcsp *chip) | |||
174 | atomic_set(&chip->timer_active, 1); | 145 | atomic_set(&chip->timer_active, 1); |
175 | chip->thalf = 0; | 146 | chip->thalf = 0; |
176 | 147 | ||
177 | tasklet_schedule(&pcsp_start_timer_tasklet); | 148 | hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); |
178 | } | 149 | } |
179 | 150 | ||
180 | static void pcsp_stop_playing(struct snd_pcsp *chip) | 151 | static void pcsp_stop_playing(struct snd_pcsp *chip) |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6d4df45e81e0..864b2f598c38 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -2981,7 +2981,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { | |||
2981 | /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */ | 2981 | /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */ |
2982 | SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG), | 2982 | SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG), |
2983 | SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG), | 2983 | SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG), |
2984 | SND_PCI_QUIRK(0x1043, 0x814e, "ASUS", ALC880_ASUS), | 2984 | SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG), |
2985 | SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), | 2985 | SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG), |
2986 | SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), | 2986 | SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST), |
2987 | SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), | 2987 | SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST), |
@@ -8757,35 +8757,39 @@ static struct hda_input_mux alc262_HP_D7000_capture_source = { | |||
8757 | }, | 8757 | }, |
8758 | }; | 8758 | }; |
8759 | 8759 | ||
8760 | /* mute/unmute internal speaker according to the hp jack and mute state */ | 8760 | /* mute/unmute internal speaker according to the hp jacks and mute state */ |
8761 | static void alc262_fujitsu_automute(struct hda_codec *codec, int force) | 8761 | static void alc262_fujitsu_automute(struct hda_codec *codec, int force) |
8762 | { | 8762 | { |
8763 | struct alc_spec *spec = codec->spec; | 8763 | struct alc_spec *spec = codec->spec; |
8764 | unsigned int mute; | 8764 | unsigned int mute; |
8765 | 8765 | ||
8766 | if (force || !spec->sense_updated) { | 8766 | if (force || !spec->sense_updated) { |
8767 | unsigned int present_int_hp, present_dock_hp; | 8767 | unsigned int present; |
8768 | /* need to execute and sync at first */ | 8768 | /* need to execute and sync at first */ |
8769 | snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0); | 8769 | snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0); |
8770 | present_int_hp = snd_hda_codec_read(codec, 0x14, 0, | 8770 | /* check laptop HP jack */ |
8771 | AC_VERB_GET_PIN_SENSE, 0); | 8771 | present = snd_hda_codec_read(codec, 0x14, 0, |
8772 | snd_hda_codec_read(codec, 0x1B, 0, AC_VERB_SET_PIN_SENSE, 0); | 8772 | AC_VERB_GET_PIN_SENSE, 0); |
8773 | present_dock_hp = snd_hda_codec_read(codec, 0x1b, 0, | 8773 | /* need to execute and sync at first */ |
8774 | AC_VERB_GET_PIN_SENSE, 0); | 8774 | snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); |
8775 | spec->jack_present = (present_int_hp & 0x80000000) != 0; | 8775 | /* check docking HP jack */ |
8776 | spec->jack_present |= (present_dock_hp & 0x80000000) != 0; | 8776 | present |= snd_hda_codec_read(codec, 0x1b, 0, |
8777 | AC_VERB_GET_PIN_SENSE, 0); | ||
8778 | if (present & AC_PINSENSE_PRESENCE) | ||
8779 | spec->jack_present = 1; | ||
8780 | else | ||
8781 | spec->jack_present = 0; | ||
8777 | spec->sense_updated = 1; | 8782 | spec->sense_updated = 1; |
8778 | } | 8783 | } |
8779 | if (spec->jack_present) { | 8784 | /* unmute internal speaker only if both HPs are unplugged and |
8780 | /* mute internal speaker */ | 8785 | * master switch is on |
8781 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | 8786 | */ |
8782 | HDA_AMP_MUTE, HDA_AMP_MUTE); | 8787 | if (spec->jack_present) |
8783 | } else { | 8788 | mute = HDA_AMP_MUTE; |
8784 | /* unmute internal speaker if necessary */ | 8789 | else |
8785 | mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); | 8790 | mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0); |
8786 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, | 8791 | snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0, |
8787 | HDA_AMP_MUTE, mute); | 8792 | HDA_AMP_MUTE, mute); |
8788 | } | ||
8789 | } | 8793 | } |
8790 | 8794 | ||
8791 | /* unsolicited event for HP jack sensing */ | 8795 | /* unsolicited event for HP jack sensing */ |
@@ -8797,6 +8801,11 @@ static void alc262_fujitsu_unsol_event(struct hda_codec *codec, | |||
8797 | alc262_fujitsu_automute(codec, 1); | 8801 | alc262_fujitsu_automute(codec, 1); |
8798 | } | 8802 | } |
8799 | 8803 | ||
8804 | static void alc262_fujitsu_init_hook(struct hda_codec *codec) | ||
8805 | { | ||
8806 | alc262_fujitsu_automute(codec, 1); | ||
8807 | } | ||
8808 | |||
8800 | /* bind volumes of both NID 0x0c and 0x0d */ | 8809 | /* bind volumes of both NID 0x0c and 0x0d */ |
8801 | static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = { | 8810 | static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = { |
8802 | .ops = &snd_hda_bind_vol, | 8811 | .ops = &snd_hda_bind_vol, |
@@ -9570,6 +9579,7 @@ static struct alc_config_preset alc262_presets[] = { | |||
9570 | .channel_mode = alc262_modes, | 9579 | .channel_mode = alc262_modes, |
9571 | .input_mux = &alc262_fujitsu_capture_source, | 9580 | .input_mux = &alc262_fujitsu_capture_source, |
9572 | .unsol_event = alc262_fujitsu_unsol_event, | 9581 | .unsol_event = alc262_fujitsu_unsol_event, |
9582 | .init_hook = alc262_fujitsu_init_hook, | ||
9573 | }, | 9583 | }, |
9574 | [ALC262_HP_BPC] = { | 9584 | [ALC262_HP_BPC] = { |
9575 | .mixers = { alc262_HP_BPC_mixer }, | 9585 | .mixers = { alc262_HP_BPC_mixer }, |