.. | .. |
---|
8 | 8 | |
---|
9 | 9 | #include <linux/device.h> |
---|
10 | 10 | #include <linux/interrupt.h> |
---|
| 11 | +#include <linux/io.h> |
---|
11 | 12 | #include <linux/pm_runtime.h> |
---|
12 | 13 | #include <linux/timecounter.h> |
---|
13 | 14 | #include <sound/core.h> |
---|
.. | .. |
---|
79 | 80 | |
---|
80 | 81 | /* misc flags */ |
---|
81 | 82 | atomic_t in_pm; /* suspend/resume being performed */ |
---|
82 | | - bool link_power_control:1; |
---|
83 | 83 | |
---|
84 | 84 | /* sysfs */ |
---|
| 85 | + struct mutex widget_lock; |
---|
85 | 86 | struct hdac_widget_tree *widgets; |
---|
86 | 87 | |
---|
87 | 88 | /* regmap */ |
---|
88 | 89 | struct regmap *regmap; |
---|
| 90 | + struct mutex regmap_lock; |
---|
89 | 91 | struct snd_array vendor_verbs; |
---|
90 | 92 | bool lazy_cache:1; /* don't wake up for writes */ |
---|
91 | 93 | bool caps_overwriting:1; /* caps overwrite being in process */ |
---|
.. | .. |
---|
97 | 99 | HDA_DEV_CORE, |
---|
98 | 100 | HDA_DEV_LEGACY, |
---|
99 | 101 | HDA_DEV_ASOC, |
---|
| 102 | +}; |
---|
| 103 | + |
---|
| 104 | +enum { |
---|
| 105 | + SND_SKL_PCI_BIND_AUTO, /* automatic selection based on pci class */ |
---|
| 106 | + SND_SKL_PCI_BIND_LEGACY,/* bind only with legacy driver */ |
---|
| 107 | + SND_SKL_PCI_BIND_ASOC /* bind only with ASoC driver */ |
---|
100 | 108 | }; |
---|
101 | 109 | |
---|
102 | 110 | /* direction */ |
---|
.. | .. |
---|
114 | 122 | int snd_hdac_device_set_chip_name(struct hdac_device *codec, const char *name); |
---|
115 | 123 | int snd_hdac_codec_modalias(struct hdac_device *hdac, char *buf, size_t size); |
---|
116 | 124 | |
---|
117 | | -int snd_hdac_refresh_widgets(struct hdac_device *codec, bool sysfs); |
---|
| 125 | +int snd_hdac_refresh_widgets(struct hdac_device *codec); |
---|
118 | 126 | |
---|
119 | | -unsigned int snd_hdac_make_cmd(struct hdac_device *codec, hda_nid_t nid, |
---|
120 | | - unsigned int verb, unsigned int parm); |
---|
121 | | -int snd_hdac_exec_verb(struct hdac_device *codec, unsigned int cmd, |
---|
122 | | - unsigned int flags, unsigned int *res); |
---|
123 | 127 | int snd_hdac_read(struct hdac_device *codec, hda_nid_t nid, |
---|
124 | 128 | unsigned int verb, unsigned int parm, unsigned int *res); |
---|
125 | 129 | int _snd_hdac_read_parm(struct hdac_device *codec, hda_nid_t nid, int parm, |
---|
.. | .. |
---|
203 | 207 | static inline int snd_hdac_keep_power_up(struct hdac_device *codec) { return 0; } |
---|
204 | 208 | static inline void snd_hdac_enter_pm(struct hdac_device *codec) {} |
---|
205 | 209 | static inline void snd_hdac_leave_pm(struct hdac_device *codec) {} |
---|
206 | | -static inline bool snd_hdac_is_in_pm(struct hdac_device *codec) { return 0; } |
---|
207 | | -static inline bool snd_hdac_is_power_on(struct hdac_device *codec) { return 1; } |
---|
| 210 | +static inline bool snd_hdac_is_in_pm(struct hdac_device *codec) { return false; } |
---|
| 211 | +static inline bool snd_hdac_is_power_on(struct hdac_device *codec) { return true; } |
---|
208 | 212 | #endif |
---|
209 | 213 | |
---|
210 | 214 | /* |
---|
.. | .. |
---|
237 | 241 | /* get a response from the last command */ |
---|
238 | 242 | int (*get_response)(struct hdac_bus *bus, unsigned int addr, |
---|
239 | 243 | unsigned int *res); |
---|
240 | | - /* control the link power */ |
---|
241 | | - int (*link_power)(struct hdac_bus *bus, bool enable); |
---|
242 | 244 | }; |
---|
243 | 245 | |
---|
244 | 246 | /* |
---|
.. | .. |
---|
247 | 249 | struct hdac_ext_bus_ops { |
---|
248 | 250 | int (*hdev_attach)(struct hdac_device *hdev); |
---|
249 | 251 | int (*hdev_detach)(struct hdac_device *hdev); |
---|
250 | | -}; |
---|
251 | | - |
---|
252 | | -/* |
---|
253 | | - * Lowlevel I/O operators |
---|
254 | | - */ |
---|
255 | | -struct hdac_io_ops { |
---|
256 | | - /* mapped register accesses */ |
---|
257 | | - void (*reg_writel)(u32 value, u32 __iomem *addr); |
---|
258 | | - u32 (*reg_readl)(u32 __iomem *addr); |
---|
259 | | - void (*reg_writew)(u16 value, u16 __iomem *addr); |
---|
260 | | - u16 (*reg_readw)(u16 __iomem *addr); |
---|
261 | | - void (*reg_writeb)(u8 value, u8 __iomem *addr); |
---|
262 | | - u8 (*reg_readb)(u8 __iomem *addr); |
---|
263 | | - /* Allocation ops */ |
---|
264 | | - int (*dma_alloc_pages)(struct hdac_bus *bus, int type, size_t size, |
---|
265 | | - struct snd_dma_buffer *buf); |
---|
266 | | - void (*dma_free_pages)(struct hdac_bus *bus, |
---|
267 | | - struct snd_dma_buffer *buf); |
---|
268 | 252 | }; |
---|
269 | 253 | |
---|
270 | 254 | #define HDA_UNSOL_QUEUE_SIZE 64 |
---|
.. | .. |
---|
294 | 278 | * @num_streams: streams supported |
---|
295 | 279 | * @idx: HDA link index |
---|
296 | 280 | * @hlink_list: link list of HDA links |
---|
297 | | - * @lock: lock for link mgmt |
---|
| 281 | + * @lock: lock for link and display power mgmt |
---|
298 | 282 | * @cmd_dma_state: state of cmd DMAs: CORB and RIRB |
---|
299 | 283 | */ |
---|
300 | 284 | struct hdac_bus { |
---|
301 | 285 | struct device *dev; |
---|
302 | 286 | const struct hdac_bus_ops *ops; |
---|
303 | | - const struct hdac_io_ops *io_ops; |
---|
304 | 287 | const struct hdac_ext_bus_ops *ext_ops; |
---|
305 | 288 | |
---|
306 | 289 | /* h/w resources */ |
---|
.. | .. |
---|
336 | 319 | struct hdac_rb corb; |
---|
337 | 320 | struct hdac_rb rirb; |
---|
338 | 321 | unsigned int last_cmd[HDA_MAX_CODECS]; /* last sent command */ |
---|
| 322 | + wait_queue_head_t rirb_wq; |
---|
339 | 323 | |
---|
340 | 324 | /* CORB/RIRB and position buffers */ |
---|
341 | 325 | struct snd_dma_buffer rb; |
---|
342 | 326 | struct snd_dma_buffer posbuf; |
---|
| 327 | + int dma_type; /* SNDRV_DMA_TYPE_XXX for CORB/RIRB */ |
---|
343 | 328 | |
---|
344 | 329 | /* hdac_stream linked list */ |
---|
345 | 330 | struct list_head stream_list; |
---|
.. | .. |
---|
348 | 333 | bool chip_init:1; /* h/w initialized */ |
---|
349 | 334 | |
---|
350 | 335 | /* behavior flags */ |
---|
| 336 | + bool aligned_mmio:1; /* aligned MMIO access */ |
---|
351 | 337 | bool sync_write:1; /* sync after verb write */ |
---|
352 | 338 | bool use_posbuf:1; /* use position buffer */ |
---|
353 | 339 | bool snoop:1; /* enable snooping */ |
---|
354 | 340 | bool align_bdle_4k:1; /* BDLE align 4K boundary */ |
---|
355 | 341 | bool reverse_assign:1; /* assign devices in reverse order */ |
---|
356 | 342 | bool corbrp_self_clear:1; /* CORBRP clears itself after reset */ |
---|
| 343 | + bool polling_mode:1; |
---|
| 344 | + bool needs_damn_long_delay:1; |
---|
| 345 | + |
---|
| 346 | + int poll_count; |
---|
357 | 347 | |
---|
358 | 348 | int bdl_pos_adj; /* BDL position adjustment */ |
---|
| 349 | + |
---|
| 350 | + /* delay time in us for dma stop */ |
---|
| 351 | + unsigned int dma_stop_delay; |
---|
359 | 352 | |
---|
360 | 353 | /* locks */ |
---|
361 | 354 | spinlock_t reg_lock; |
---|
362 | 355 | struct mutex cmd_mutex; |
---|
| 356 | + struct mutex lock; |
---|
363 | 357 | |
---|
364 | 358 | /* DRM component interface */ |
---|
365 | 359 | struct drm_audio_component *audio_component; |
---|
366 | | - int drm_power_refcount; |
---|
| 360 | + long display_power_status; |
---|
| 361 | + unsigned long display_power_active; |
---|
367 | 362 | |
---|
368 | 363 | /* parameters required for enhanced capabilities */ |
---|
369 | 364 | int num_streams; |
---|
370 | 365 | int idx; |
---|
371 | 366 | |
---|
| 367 | + /* link management */ |
---|
372 | 368 | struct list_head hlink_list; |
---|
373 | | - |
---|
374 | | - struct mutex lock; |
---|
375 | 369 | bool cmd_dma_state; |
---|
376 | 370 | |
---|
| 371 | + /* factor used to derive STRIPE control value */ |
---|
| 372 | + unsigned int sdo_limit; |
---|
377 | 373 | }; |
---|
378 | 374 | |
---|
379 | 375 | int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, |
---|
380 | | - const struct hdac_bus_ops *ops, |
---|
381 | | - const struct hdac_io_ops *io_ops); |
---|
| 376 | + const struct hdac_bus_ops *ops); |
---|
382 | 377 | void snd_hdac_bus_exit(struct hdac_bus *bus); |
---|
383 | | -int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, |
---|
384 | | - unsigned int cmd, unsigned int *res); |
---|
385 | 378 | int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr, |
---|
386 | 379 | unsigned int cmd, unsigned int *res); |
---|
387 | | -void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex); |
---|
388 | | - |
---|
389 | | -int snd_hdac_bus_add_device(struct hdac_bus *bus, struct hdac_device *codec); |
---|
390 | | -void snd_hdac_bus_remove_device(struct hdac_bus *bus, |
---|
391 | | - struct hdac_device *codec); |
---|
392 | 380 | |
---|
393 | 381 | static inline void snd_hdac_codec_link_up(struct hdac_device *codec) |
---|
394 | 382 | { |
---|
.. | .. |
---|
404 | 392 | int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, |
---|
405 | 393 | unsigned int *res); |
---|
406 | 394 | int snd_hdac_bus_parse_capabilities(struct hdac_bus *bus); |
---|
407 | | -int snd_hdac_link_power(struct hdac_device *codec, bool enable); |
---|
408 | 395 | |
---|
409 | 396 | bool snd_hdac_bus_init_chip(struct hdac_bus *bus, bool full_reset); |
---|
410 | 397 | void snd_hdac_bus_stop_chip(struct hdac_bus *bus); |
---|
.. | .. |
---|
422 | 409 | int snd_hdac_bus_alloc_stream_pages(struct hdac_bus *bus); |
---|
423 | 410 | void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus); |
---|
424 | 411 | |
---|
| 412 | +#ifdef CONFIG_SND_HDA_ALIGNED_MMIO |
---|
| 413 | +unsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask); |
---|
| 414 | +void snd_hdac_aligned_write(unsigned int val, void __iomem *addr, |
---|
| 415 | + unsigned int mask); |
---|
| 416 | +#define snd_hdac_aligned_mmio(bus) (bus)->aligned_mmio |
---|
| 417 | +#else |
---|
| 418 | +#define snd_hdac_aligned_mmio(bus) false |
---|
| 419 | +#define snd_hdac_aligned_read(addr, mask) 0 |
---|
| 420 | +#define snd_hdac_aligned_write(val, addr, mask) do {} while (0) |
---|
| 421 | +#endif |
---|
| 422 | + |
---|
| 423 | +static inline void snd_hdac_reg_writeb(struct hdac_bus *bus, void __iomem *addr, |
---|
| 424 | + u8 val) |
---|
| 425 | +{ |
---|
| 426 | + if (snd_hdac_aligned_mmio(bus)) |
---|
| 427 | + snd_hdac_aligned_write(val, addr, 0xff); |
---|
| 428 | + else |
---|
| 429 | + writeb(val, addr); |
---|
| 430 | +} |
---|
| 431 | + |
---|
| 432 | +static inline void snd_hdac_reg_writew(struct hdac_bus *bus, void __iomem *addr, |
---|
| 433 | + u16 val) |
---|
| 434 | +{ |
---|
| 435 | + if (snd_hdac_aligned_mmio(bus)) |
---|
| 436 | + snd_hdac_aligned_write(val, addr, 0xffff); |
---|
| 437 | + else |
---|
| 438 | + writew(val, addr); |
---|
| 439 | +} |
---|
| 440 | + |
---|
| 441 | +static inline u8 snd_hdac_reg_readb(struct hdac_bus *bus, void __iomem *addr) |
---|
| 442 | +{ |
---|
| 443 | + return snd_hdac_aligned_mmio(bus) ? |
---|
| 444 | + snd_hdac_aligned_read(addr, 0xff) : readb(addr); |
---|
| 445 | +} |
---|
| 446 | + |
---|
| 447 | +static inline u16 snd_hdac_reg_readw(struct hdac_bus *bus, void __iomem *addr) |
---|
| 448 | +{ |
---|
| 449 | + return snd_hdac_aligned_mmio(bus) ? |
---|
| 450 | + snd_hdac_aligned_read(addr, 0xffff) : readw(addr); |
---|
| 451 | +} |
---|
| 452 | + |
---|
| 453 | +#define snd_hdac_reg_writel(bus, addr, val) writel(val, addr) |
---|
| 454 | +#define snd_hdac_reg_readl(bus, addr) readl(addr) |
---|
| 455 | + |
---|
425 | 456 | /* |
---|
426 | 457 | * macros for easy use |
---|
427 | 458 | */ |
---|
428 | 459 | #define _snd_hdac_chip_writeb(chip, reg, value) \ |
---|
429 | | - ((chip)->io_ops->reg_writeb(value, (chip)->remap_addr + (reg))) |
---|
| 460 | + snd_hdac_reg_writeb(chip, (chip)->remap_addr + (reg), value) |
---|
430 | 461 | #define _snd_hdac_chip_readb(chip, reg) \ |
---|
431 | | - ((chip)->io_ops->reg_readb((chip)->remap_addr + (reg))) |
---|
| 462 | + snd_hdac_reg_readb(chip, (chip)->remap_addr + (reg)) |
---|
432 | 463 | #define _snd_hdac_chip_writew(chip, reg, value) \ |
---|
433 | | - ((chip)->io_ops->reg_writew(value, (chip)->remap_addr + (reg))) |
---|
| 464 | + snd_hdac_reg_writew(chip, (chip)->remap_addr + (reg), value) |
---|
434 | 465 | #define _snd_hdac_chip_readw(chip, reg) \ |
---|
435 | | - ((chip)->io_ops->reg_readw((chip)->remap_addr + (reg))) |
---|
| 466 | + snd_hdac_reg_readw(chip, (chip)->remap_addr + (reg)) |
---|
436 | 467 | #define _snd_hdac_chip_writel(chip, reg, value) \ |
---|
437 | | - ((chip)->io_ops->reg_writel(value, (chip)->remap_addr + (reg))) |
---|
| 468 | + snd_hdac_reg_writel(chip, (chip)->remap_addr + (reg), value) |
---|
438 | 469 | #define _snd_hdac_chip_readl(chip, reg) \ |
---|
439 | | - ((chip)->io_ops->reg_readl((chip)->remap_addr + (reg))) |
---|
| 470 | + snd_hdac_reg_readl(chip, (chip)->remap_addr + (reg)) |
---|
440 | 471 | |
---|
441 | 472 | /* read/write a register, pass without AZX_REG_ prefix */ |
---|
442 | 473 | #define snd_hdac_chip_writel(chip, reg, value) \ |
---|
.. | .. |
---|
485 | 516 | struct snd_pcm_substream *substream; /* assigned substream, |
---|
486 | 517 | * set in PCM open |
---|
487 | 518 | */ |
---|
| 519 | + struct snd_compr_stream *cstream; |
---|
488 | 520 | unsigned int format_val; /* format value to be set in the |
---|
489 | 521 | * controller and the codec |
---|
490 | 522 | */ |
---|
.. | .. |
---|
497 | 529 | bool prepared:1; |
---|
498 | 530 | bool no_period_wakeup:1; |
---|
499 | 531 | bool locked:1; |
---|
| 532 | + bool stripe:1; /* apply stripe control */ |
---|
500 | 533 | |
---|
| 534 | + u64 curr_pos; |
---|
501 | 535 | /* timestamp */ |
---|
502 | 536 | unsigned long start_wallclk; /* start + minimum wallclk */ |
---|
503 | 537 | unsigned long period_wallclk; /* wallclk for period */ |
---|
.. | .. |
---|
528 | 562 | void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start); |
---|
529 | 563 | void snd_hdac_stream_clear(struct hdac_stream *azx_dev); |
---|
530 | 564 | void snd_hdac_stream_stop(struct hdac_stream *azx_dev); |
---|
| 565 | +void snd_hdac_stop_streams(struct hdac_bus *bus); |
---|
| 566 | +void snd_hdac_stop_streams_and_chip(struct hdac_bus *bus); |
---|
531 | 567 | void snd_hdac_stream_reset(struct hdac_stream *azx_dev); |
---|
532 | 568 | void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set, |
---|
533 | 569 | unsigned int streams, unsigned int reg); |
---|
.. | .. |
---|
535 | 571 | unsigned int streams); |
---|
536 | 572 | void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, |
---|
537 | 573 | unsigned int streams); |
---|
| 574 | +int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus, |
---|
| 575 | + struct snd_pcm_substream *substream); |
---|
| 576 | + |
---|
538 | 577 | /* |
---|
539 | 578 | * macros for easy use |
---|
540 | 579 | */ |
---|
541 | | -#define _snd_hdac_stream_write(type, dev, reg, value) \ |
---|
542 | | - ((dev)->bus->io_ops->reg_write ## type(value, (dev)->sd_addr + (reg))) |
---|
543 | | -#define _snd_hdac_stream_read(type, dev, reg) \ |
---|
544 | | - ((dev)->bus->io_ops->reg_read ## type((dev)->sd_addr + (reg))) |
---|
545 | | - |
---|
546 | 580 | /* read/write a register, pass without AZX_REG_ prefix */ |
---|
547 | 581 | #define snd_hdac_stream_writel(dev, reg, value) \ |
---|
548 | | - _snd_hdac_stream_write(l, dev, AZX_REG_ ## reg, value) |
---|
| 582 | + snd_hdac_reg_writel((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value) |
---|
549 | 583 | #define snd_hdac_stream_writew(dev, reg, value) \ |
---|
550 | | - _snd_hdac_stream_write(w, dev, AZX_REG_ ## reg, value) |
---|
| 584 | + snd_hdac_reg_writew((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value) |
---|
551 | 585 | #define snd_hdac_stream_writeb(dev, reg, value) \ |
---|
552 | | - _snd_hdac_stream_write(b, dev, AZX_REG_ ## reg, value) |
---|
| 586 | + snd_hdac_reg_writeb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value) |
---|
553 | 587 | #define snd_hdac_stream_readl(dev, reg) \ |
---|
554 | | - _snd_hdac_stream_read(l, dev, AZX_REG_ ## reg) |
---|
| 588 | + snd_hdac_reg_readl((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg) |
---|
555 | 589 | #define snd_hdac_stream_readw(dev, reg) \ |
---|
556 | | - _snd_hdac_stream_read(w, dev, AZX_REG_ ## reg) |
---|
| 590 | + snd_hdac_reg_readw((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg) |
---|
557 | 591 | #define snd_hdac_stream_readb(dev, reg) \ |
---|
558 | | - _snd_hdac_stream_read(b, dev, AZX_REG_ ## reg) |
---|
| 592 | + snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg) |
---|
559 | 593 | |
---|
560 | 594 | /* update a register, pass without AZX_REG_ prefix */ |
---|
561 | 595 | #define snd_hdac_stream_updatel(dev, reg, mask, val) \ |
---|