Advertisement
Guest User

pao

a guest
Feb 9th, 2010
1,957
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 33.80 KB | None | 0 0
  1. diff --git a/pci/hda/patch_nvhdmi.c b/pci/hda/patch_nvhdmi.c
  2. index 6afdab0..91fe3a2 100644
  3. --- a/pci/hda/patch_nvhdmi.c
  4. +++ b/pci/hda/patch_nvhdmi.c
  5. @@ -29,33 +29,236 @@
  6. #include "hda_codec.h"
  7. #include "hda_local.h"
  8.  
  9. -/* define below to restrict the supported rates and formats */
  10. -/* #define LIMITED_RATE_FMT_SUPPORT */
  11. +enum HDACodec {
  12. + HDA_CODEC_NVIDIA_MCP7X,
  13. + HDA_CODEC_NVIDIA_MCP89,
  14. + HDA_CODEC_NVIDIA_GT21X,
  15. + HDA_CODEC_INVALID
  16. +};
  17. +
  18. +struct hdmi_audio_infoframe {
  19. + u8 type; /* 0x84 */
  20. + u8 ver; /* 0x01 */
  21. + u8 len; /* 0x0a */
  22. +
  23. + u8 checksum; /* PB0 */
  24. + u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */
  25. + u8 SS01_SF24;
  26. + u8 CXT04;
  27. + u8 CA;
  28. + u8 LFEPBL01_LSV36_DM_INH7;
  29. +};
  30.  
  31. +/*
  32. + * CEA speaker placement:
  33. + *
  34. + * FLH FCH FRH
  35. + * FLW FL FLC FC FRC FR FRW
  36. + *
  37. + * LFE
  38. + * TC
  39. + *
  40. + * RL RLC RC RRC RR
  41. + *
  42. + * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
  43. + * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
  44. + */
  45. +enum cea_speaker_placement {
  46. + FL = (1 << 0), /* Front Left */
  47. + FC = (1 << 1), /* Front Center */
  48. + FR = (1 << 2), /* Front Right */
  49. + FLC = (1 << 3), /* Front Left Center */
  50. + FRC = (1 << 4), /* Front Right Center */
  51. + RL = (1 << 5), /* Rear Left */
  52. + RC = (1 << 6), /* Rear Center */
  53. + RR = (1 << 7), /* Rear Right */
  54. + RLC = (1 << 8), /* Rear Left Center */
  55. + RRC = (1 << 9), /* Rear Right Center */
  56. + LFE = (1 << 10), /* Low Frequency Effect */
  57. + FLW = (1 << 11), /* Front Left Wide */
  58. + FRW = (1 << 12), /* Front Right Wide */
  59. + FLH = (1 << 13), /* Front Left High */
  60. + FCH = (1 << 14), /* Front Center High */
  61. + FRH = (1 << 15), /* Front Right High */
  62. + TC = (1 << 16), /* Top Center */
  63. +};
  64. +
  65. +/*
  66. + * ELD SA bits in the CEA Speaker Allocation data block
  67. + */
  68. +static int eld_speaker_allocation_bits[] = {
  69. + [0] = FL | FR,
  70. + [1] = LFE,
  71. + [2] = FC,
  72. + [3] = RL | RR,
  73. + [4] = RC,
  74. + [5] = FLC | FRC,
  75. + [6] = RLC | RRC,
  76. + /* the following are not defined in ELD yet */
  77. + [7] = FLW | FRW,
  78. + [8] = FLH | FRH,
  79. + [9] = TC,
  80. + [10] = FCH,
  81. +};
  82. +
  83. +struct cea_channel_speaker_allocation {
  84. + int ca_index;
  85. + int speakers[8];
  86. +
  87. + /* derived values, just for convenience */
  88. + int channels;
  89. + int spk_mask;
  90. +};
  91. +
  92. +/*
  93. + * This is an ordered list!
  94. + *
  95. + * The preceding ones have better chances to be selected by
  96. + * hdmi_setup_channel_allocation().
  97. + */
  98. +static struct cea_channel_speaker_allocation channel_allocations[] = {
  99. +/* channel: 8 7 6 5 4 3 2 1 */
  100. +{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } },
  101. + /* 2.1 */
  102. +{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
  103. + /* Dolby Surround */
  104. +{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
  105. +{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
  106. +{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
  107. +{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
  108. +{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
  109. +{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
  110. +{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
  111. +{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
  112. +{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
  113. + /* 5.1 */
  114. +{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
  115. +{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
  116. +{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
  117. +{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
  118. + /* 6.1 */
  119. +{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
  120. +{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
  121. +{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
  122. +{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
  123. + /* 7.1 */
  124. +{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
  125. +{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
  126. +{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
  127. +{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
  128. +{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } },
  129. +{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } },
  130. +{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } },
  131. +{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } },
  132. +{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } },
  133. +{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } },
  134. +{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } },
  135. +{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } },
  136. +{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } },
  137. +{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } },
  138. +{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } },
  139. +{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } },
  140. +{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } },
  141. +{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } },
  142. +{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } },
  143. +{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } },
  144. +{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } },
  145. +{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } },
  146. +{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } },
  147. +{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } },
  148. +{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } },
  149. +{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } },
  150. +{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } },
  151. +{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } },
  152. +{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } },
  153. +{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } },
  154. +{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } },
  155. +};
  156. +
  157. +/*
  158. + * ELD: EDID Like Data
  159. + */
  160. +#define ELD_MAX_MNL 16
  161. +#define ELD_MAX_SAD 16
  162. +/*
  163. +struct hdmi_eld {
  164. + bool monitor_present;
  165. + bool eld_valid;
  166. + int eld_size;
  167. + int baseline_len;
  168. + int eld_ver;
  169. + int cea_edid_ver;
  170. + char monitor_name[ELD_MAX_MNL + 1];
  171. + int manufacture_id;
  172. + int product_id;
  173. + u64 port_id;
  174. + int support_hdcp;
  175. + int support_ai;
  176. + int conn_type;
  177. + int aud_synch_delay;
  178. + int spk_alloc;
  179. + int sad_count;
  180. +// struct cea_sad sad[ELD_MAX_SAD];
  181. +};
  182. +*/
  183. struct nvhdmi_spec {
  184. struct hda_multi_out multiout;
  185.  
  186. struct hda_pcm pcm_rec;
  187. +
  188. + /*
  189. + * HDMI sink attached to each pin
  190. + */
  191. + struct hdmi_eld sink_eld[1];
  192. + unsigned int codec_type;
  193. };
  194.  
  195. -#define Nv_VERB_SET_Channel_Allocation 0xF79
  196. -#define Nv_VERB_SET_Info_Frame_Checksum 0xF7A
  197. -#define Nv_VERB_SET_Audio_Protection_On 0xF98
  198. -#define Nv_VERB_SET_Audio_Protection_Off 0xF99
  199. +#define AC_DIPXMIT_DISABLE (0x0<<6)
  200. +#define AC_DIPXMIT_BEST (0x3<<6)
  201. +
  202. +#define AC_VERB_GET_CVT_CHAN_COUNT 0xf2d
  203. +#define AC_VERB_GET_HDMI_DIP_DATA 0xf31
  204. +#define AC_VERB_GET_HDMI_DIP_XMIT 0xf32
  205. +
  206. +#define AC_VERB_SET_CVT_CHAN_COUNT 0x72d
  207. +#define AC_VERB_SET_HDMI_DIP_INDEX 0x730
  208. +#define AC_VERB_SET_HDMI_DIP_DATA 0x731
  209. +#define AC_VERB_SET_HDMI_DIP_XMIT 0x732
  210. +#define AC_VERB_SET_HDMI_CHAN_SLOT 0x734
  211.  
  212. -#define Nv_Master_Convert_nid 0x04
  213. -#define Nv_Master_Pin_nid 0x05
  214. +#define Nv_VERB_SET_Channel_Allocation 0xF79
  215. +#define Nv_VERB_SET_Info_Frame_Checksum 0xF7A
  216. +#define Nv_VERB_SET_Audio_Protection_On 0xF98
  217. +#define Nv_VERB_SET_Audio_Protection_Off 0xF99
  218.  
  219. -static hda_nid_t nvhdmi_convert_nids[4] = {
  220. +#define Nv_Master_Convert_nid 0x04
  221. +#define Nv_Master_Pin_nid 0x05
  222. +
  223. +#define nvhdmi_convert_nids_89 0x04
  224. +#define nvhdmi_pin_nids_89 0x05
  225. +
  226. +static hda_nid_t nvhdmi_convert_nids_7x[4] = {
  227. /*front, rear, clfe, rear_surr */
  228. 0x6, 0x8, 0xa, 0xc,
  229. };
  230.  
  231. -static struct hda_verb nvhdmi_basic_init[] = {
  232. +#if 0
  233. +static hda_nid_t nvhdmi_pin_nids_7x[4] = {
  234. + /*front, rear, clfe, rear_surr */
  235. + 0x7, 0x9, 0xb, 0xd,
  236. +};
  237. +#endif
  238. +
  239. +static struct hda_verb nvhdmi_basic_init_89[] = {
  240. + /* enable digital output on pin widget */
  241. + { 0x5, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
  242. + { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
  243. + {} /* terminator */
  244. +};
  245. +static struct hda_verb nvhdmi_basic_init_7x[] = {
  246. /* set audio protect on */
  247. { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
  248. /* enable digital output on pin widget */
  249. - { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
  250. { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
  251. { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
  252. { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
  253. @@ -63,22 +266,330 @@ static struct hda_verb nvhdmi_basic_init[] = {
  254. {} /* terminator */
  255. };
  256.  
  257. -#ifdef LIMITED_RATE_FMT_SUPPORT
  258. -/* support only the safe format and rate */
  259. -#define SUPPORTED_RATES SNDRV_PCM_RATE_48000
  260. -#define SUPPORTED_MAXBPS 16
  261. -#define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE
  262. -#else
  263. -/* support all rates and formats */
  264. -#define SUPPORTED_RATES \
  265. - (SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
  266. - SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
  267. - SNDRV_PCM_RATE_192000)
  268. -#define SUPPORTED_MAXBPS 24
  269. -#define SUPPORTED_FORMATS \
  270. - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
  271. +static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
  272. + int packet_index, int byte_index)
  273. +{
  274. + int val;
  275. +
  276. + val = (packet_index << 5) | (byte_index & 0x1f);
  277. +
  278. + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
  279. +}
  280. +
  281. +static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
  282. + unsigned char val)
  283. +{
  284. + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
  285. +}
  286. +
  287. +static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
  288. +{
  289. + /* Unmute */
  290. + if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
  291. + snd_hda_codec_write(codec, pin_nid, 0,
  292. + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
  293. + /* Enable pin out */
  294. + snd_hda_codec_write(codec, pin_nid, 0,
  295. + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
  296. +}
  297. +
  298. +/*
  299. + * Enable Audio InfoFrame Transmission
  300. + */
  301. +static void hdmi_start_infoframe_trans(struct hda_codec *codec,
  302. + hda_nid_t pin_nid)
  303. +{
  304. + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
  305. + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
  306. + AC_DIPXMIT_BEST);
  307. +}
  308. +
  309. +/*
  310. + * Disable Audio InfoFrame Transmission
  311. + */
  312. +static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
  313. + hda_nid_t pin_nid)
  314. +{
  315. + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
  316. + snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
  317. + AC_DIPXMIT_DISABLE);
  318. +}
  319. +
  320. +static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
  321. +{
  322. + return 1 + snd_hda_codec_read(codec, nid, 0,
  323. + AC_VERB_GET_CVT_CHAN_COUNT, 0);
  324. +}
  325. +
  326. +static void hdmi_set_channel_count(struct hda_codec *codec,
  327. + hda_nid_t nid, int chs)
  328. +{
  329. + if (chs != hdmi_get_channel_count(codec, nid))
  330. + snd_hda_codec_write(codec, nid, 0,
  331. + AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
  332. +}
  333. +
  334. +static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
  335. +{
  336. + u8 *bytes = (u8 *)ai;
  337. + ai->checksum = 0;
  338. +/*
  339. + u8 sum = 0;
  340. + int i;
  341. +
  342. + ai->checksum = 0;
  343. +
  344. + for (i = 0; i < sizeof(*ai); i++)
  345. + sum += bytes[i];
  346. +
  347. + ai->checksum = - sum;
  348. +*/
  349. +}
  350. +
  351. +static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
  352. + hda_nid_t pin_nid,
  353. + struct hdmi_audio_infoframe *ai)
  354. +{
  355. + u8 *bytes = (u8 *)ai;
  356. + int i;
  357. +
  358. + hdmi_checksum_audio_infoframe(ai);
  359. +
  360. + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
  361. + for (i = 0; i < sizeof(*ai); i++)
  362. + hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
  363. +}
  364. +
  365. +/*
  366. + * Compute derived values in channel_allocations[].
  367. + */
  368. +static void init_channel_allocations(void)
  369. +{
  370. + int i, j;
  371. + struct cea_channel_speaker_allocation *p;
  372. +
  373. + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
  374. + p = channel_allocations + i;
  375. + p->channels = 0;
  376. + p->spk_mask = 0;
  377. + for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
  378. + if (p->speakers[j]) {
  379. + p->channels++;
  380. + p->spk_mask |= p->speakers[j];
  381. + }
  382. + }
  383. +}
  384. +
  385. +/*
  386. + * The transformation takes two steps:
  387. + *
  388. + * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
  389. + * spk_mask => (channel_allocations[]) => ai->CA
  390. + *
  391. + * TODO: it could select the wrong CA from multiple candidates.
  392. +*/
  393. +static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
  394. + struct hdmi_audio_infoframe *ai)
  395. +{
  396. + struct intel_hdmi_spec *spec = codec->spec;
  397. + struct hdmi_eld *eld;
  398. + int i;
  399. + int spk_mask = 0;
  400. + int channels = 1 + (ai->CC02_CT47 & 0x7);
  401. +
  402. + switch (channels)
  403. + {
  404. + default:
  405. + case 0:
  406. + case 2:
  407. + ai->CA = 0;
  408. + break;
  409. + case 4:
  410. + ai->CA = 0x08;
  411. +// ai->CA = 0x06;
  412. + break;
  413. + case 6:
  414. + ai->CA = 0x0b;
  415. + break;
  416. + case 8:
  417. + ai->CA = 0x13;
  418. +// ai->CA = 0x1A;
  419. + break;
  420. + }
  421. +#if 0
  422. + /*
  423. + * CA defaults to 0 for basic stereo audio
  424. + */
  425. + if (channels <= 2)
  426. + return 0;
  427. +
  428. + i = hda_node_index(spec->pin_cvt, nid);
  429. + if (i < 0)
  430. + return 0;
  431. + eld = &spec->sink_eld[i];
  432. +
  433. + /*
  434. + * HDMI sink's ELD info cannot always be retrieved for now, e.g.
  435. + * in console or for audio devices. Assume the highest speakers
  436. + * configuration, to _not_ prohibit multi-channel audio playback.
  437. + */
  438. + if (!eld->spk_alloc)
  439. + eld->spk_alloc = 0xffff;
  440. +
  441. + /*
  442. + * expand ELD's speaker allocation mask
  443. + *
  444. + * ELD tells the speaker mask in a compact(paired) form,
  445. + * expand ELD's notions to match the ones used by Audio InfoFrame.
  446. + */
  447. + for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
  448. + if (eld->spk_alloc & (1 << i))
  449. + spk_mask |= eld_speaker_allocation_bits[i];
  450. + }
  451. +
  452. + /* search for the first working match in the CA table */
  453. + for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
  454. + if (channels == channel_allocations[i].channels &&
  455. + (spk_mask & channel_allocations[i].spk_mask) ==
  456. + channel_allocations[i].spk_mask) {
  457. + ai->CA = channel_allocations[i].ca_index;
  458. + break;
  459. + }
  460. + }
  461. #endif
  462.  
  463. + return ai->CA;
  464. +}
  465. +
  466. +static void hdmi_setup_channel_mapping(struct hda_codec *codec, hda_nid_t nid,
  467. + struct hdmi_audio_infoframe *ai)
  468. +{
  469. + int i;
  470. + int channels = 1 + (ai->CC02_CT47 & 0x7);
  471. + unsigned char map[8] = {0x00, 0x11, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7};
  472. +
  473. + /*
  474. + * TODO: adjust channel mapping if necessary
  475. + * ALSA sequence is front/surr/clfe/side?
  476. + */
  477. +
  478. + switch (channels) {
  479. + case 2:
  480. + break;
  481. + case 4:
  482. + if (ai->CA == 0x08)
  483. + {
  484. + map[4] = 0x24;
  485. + map[5] = 0x35;
  486. + }
  487. + else if (ai->CA == 0x06)
  488. + {
  489. + map[4] = 0x23;
  490. + map[5] = 0x34;
  491. + }
  492. +
  493. + break;
  494. + case 6:
  495. + map[2] = 0x32;
  496. + map[3] = 0x23;
  497. + map[4] = 0x44;
  498. + map[5] = 0x55;
  499. + break;
  500. + case 8:
  501. + map[2] = 0x32;
  502. + map[3] = 0x23;
  503. + map[4] = 0x64;
  504. + map[5] = 0x75;
  505. + map[6] = 0x46;
  506. + map[7] = 0x57;
  507. + break;
  508. +
  509. + }
  510. +
  511. + for (i = 0; i < 8; i++)
  512. + {
  513. + snd_hda_codec_write(codec, nid, 0,
  514. + AC_VERB_SET_HDMI_CHAN_SLOT,
  515. + map[i]);
  516. + }
  517. +
  518. +}
  519. +
  520. +static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
  521. + struct hdmi_audio_infoframe *ai)
  522. +{
  523. + u8 *bytes = (u8 *)ai;
  524. + u8 val;
  525. + int i;
  526. +
  527. + if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
  528. + != AC_DIPXMIT_BEST)
  529. + return false;
  530. +
  531. + hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
  532. + for (i = 0; i < sizeof(*ai); i++) {
  533. + val = snd_hda_codec_read(codec, pin_nid, 0,
  534. + AC_VERB_GET_HDMI_DIP_DATA, 0);
  535. + if (val != bytes[i])
  536. + return false;
  537. + }
  538. +
  539. + return true;
  540. +}
  541. +
  542. +static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
  543. + struct snd_pcm_substream *substream)
  544. +{
  545. + struct intel_hdmi_spec *spec = codec->spec;
  546. + hda_nid_t pin_nid;
  547. + int i;
  548. + struct hdmi_audio_infoframe ai = {
  549. + .type = 0x84,
  550. + .ver = 0x01,
  551. + .len = 0x0a,
  552. + .CC02_CT47 = substream->runtime->channels - 1,
  553. + };
  554. +
  555. + hdmi_setup_channel_allocation(codec, nid, &ai);
  556. +
  557. + pin_nid = nvhdmi_pin_nids_89;
  558. + hdmi_setup_channel_mapping(codec, pin_nid, &ai);
  559. +
  560. + if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
  561. + hdmi_stop_infoframe_trans(codec, pin_nid);
  562. + hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
  563. + hdmi_start_infoframe_trans(codec, pin_nid);
  564. + }
  565. +}
  566. +
  567. +/*
  568. + * Callbacks
  569. + */
  570. +
  571. +static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
  572. + u32 stream_tag, int format)
  573. +{
  574. + int tag;
  575. + int fmt;
  576. +
  577. + tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
  578. + fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
  579. +
  580. + snd_printdd("hdmi_setup_stream: "
  581. + "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
  582. + nid,
  583. + tag == stream_tag ? "" : "new-",
  584. + stream_tag,
  585. + fmt == format ? "" : "new-",
  586. + format);
  587. + if (tag != stream_tag)
  588. + snd_hda_codec_write(codec, nid, 0,
  589. + AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4);
  590. + if (fmt != format)
  591. + snd_hda_codec_write(codec, nid, 0,
  592. + AC_VERB_SET_STREAM_FORMAT, format);
  593. +}
  594. +
  595. /*
  596. * Controls
  597. */
  598. @@ -96,7 +607,16 @@ static int nvhdmi_build_controls(struct hda_codec *codec)
  599.  
  600. static int nvhdmi_init(struct hda_codec *codec)
  601. {
  602. - snd_hda_sequence_write(codec, nvhdmi_basic_init);
  603. + struct nvhdmi_spec *spec = codec->spec;
  604. + if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
  605. + || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X))
  606. + {
  607. + snd_hda_sequence_write(codec, nvhdmi_basic_init_89);
  608. + }
  609. + else
  610. + {
  611. + snd_hda_sequence_write(codec, nvhdmi_basic_init_7x);
  612. + }
  613. return 0;
  614. }
  615.  
  616. @@ -104,205 +624,169 @@ static int nvhdmi_init(struct hda_codec *codec)
  617. * Digital out
  618. */
  619. static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
  620. - struct hda_codec *codec,
  621. - struct snd_pcm_substream *substream)
  622. + struct hda_codec *codec,
  623. + struct snd_pcm_substream *substream)
  624. {
  625. struct nvhdmi_spec *spec = codec->spec;
  626. return snd_hda_multi_out_dig_open(codec, &spec->multiout);
  627. }
  628.  
  629. -static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo,
  630. - struct hda_codec *codec,
  631. - struct snd_pcm_substream *substream)
  632. +static int nvhdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
  633. + struct hda_codec *codec,
  634. + struct snd_pcm_substream *substream)
  635. {
  636. struct nvhdmi_spec *spec = codec->spec;
  637. int i;
  638.  
  639. - snd_hda_codec_write(codec, Nv_Master_Convert_nid,
  640. - 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
  641. - for (i = 0; i < 4; i++) {
  642. - /* set the stream id */
  643. - snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
  644. - AC_VERB_SET_CHANNEL_STREAMID, 0);
  645. - /* set the stream format */
  646. - snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
  647. - AC_VERB_SET_STREAM_FORMAT, 0);
  648. + if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
  649. + || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X))
  650. + {
  651. + return 0;
  652. + }
  653. + else
  654. + {
  655. + mutex_lock(&codec->spdif_mutex);
  656. + (&spec->multiout)->dig_out_used = 0;
  657. +
  658. + snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
  659. + for (i = 0; i < 4; i++)
  660. + {
  661. + /* set the stream id */
  662. + snd_hda_codec_write(codec, nvhdmi_convert_nids_7x[i], 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
  663. + /* set the stream format */
  664. + snd_hda_codec_write(codec, nvhdmi_convert_nids_7x[i], 0, AC_VERB_SET_STREAM_FORMAT, 0);
  665. + }
  666. + mutex_unlock(&codec->spdif_mutex);
  667. + return 0;
  668. }
  669. -
  670. - return snd_hda_multi_out_dig_close(codec, &spec->multiout);
  671. }
  672.  
  673. -static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo,
  674. - struct hda_codec *codec,
  675. - struct snd_pcm_substream *substream)
  676. +static int nvhdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
  677. + struct hda_codec *codec,
  678. + unsigned int stream_tag,
  679. + unsigned int format,
  680. + struct snd_pcm_substream *substream)
  681. {
  682. struct nvhdmi_spec *spec = codec->spec;
  683. - return snd_hda_multi_out_dig_close(codec, &spec->multiout);
  684. -}
  685. -
  686. -static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
  687. - struct hda_codec *codec,
  688. - unsigned int stream_tag,
  689. - unsigned int format,
  690. - struct snd_pcm_substream *substream)
  691. -{
  692. int chs;
  693. unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id;
  694. int i;
  695.  
  696. - mutex_lock(&codec->spdif_mutex);
  697. + if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
  698. + || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X))
  699. + {
  700. + hdmi_set_channel_count(codec, hinfo->nid,
  701. + substream->runtime->channels);
  702.  
  703. - chs = substream->runtime->channels;
  704. - chan = chs ? (chs - 1) : 1;
  705. + hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
  706.  
  707. - switch (chs) {
  708. - default:
  709. - case 0:
  710. - case 2:
  711. - chanmask = 0x00;
  712. - break;
  713. - case 4:
  714. - chanmask = 0x08;
  715. - break;
  716. - case 6:
  717. - chanmask = 0x0b;
  718. - break;
  719. - case 8:
  720. - chanmask = 0x13;
  721. - break;
  722. + hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
  723. + return 0;
  724. }
  725. - dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
  726. - dataDCC2 = 0x2;
  727. -
  728. - /* set the Audio InforFrame Channel Allocation */
  729. - snd_hda_codec_write(codec, 0x1, 0,
  730. - Nv_VERB_SET_Channel_Allocation, chanmask);
  731. -
  732. - /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
  733. - if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
  734. - snd_hda_codec_write(codec,
  735. - Nv_Master_Convert_nid,
  736. - 0,
  737. - AC_VERB_SET_DIGI_CONVERT_1,
  738. - codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
  739. + else
  740. + {
  741. + mutex_lock(&codec->spdif_mutex);
  742. +
  743. + chs = substream->runtime->channels;
  744. + chan = chs ? (chs - 1) : 1;
  745. +
  746. + switch (chs)
  747. + {
  748. + default:
  749. + case 0:
  750. + case 2:
  751. + chanmask = 0x00;
  752. + break;
  753. + case 4:
  754. + chanmask = 0x08;
  755. + break;
  756. + case 6:
  757. + chanmask = 0x0b;
  758. + break;
  759. + case 8:
  760. + chanmask = 0x13;
  761. + break;
  762. + }
  763. + dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
  764. + dataDCC2 = 0x2;
  765.  
  766. - /* set the stream id */
  767. - snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
  768. - AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
  769. -
  770. - /* set the stream format */
  771. - snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
  772. - AC_VERB_SET_STREAM_FORMAT, format);
  773. -
  774. - /* turn on again (if needed) */
  775. - /* enable and set the channel status audio/data flag */
  776. - if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
  777. - snd_hda_codec_write(codec,
  778. - Nv_Master_Convert_nid,
  779. - 0,
  780. - AC_VERB_SET_DIGI_CONVERT_1,
  781. - codec->spdif_ctls & 0xff);
  782. - snd_hda_codec_write(codec,
  783. - Nv_Master_Convert_nid,
  784. - 0,
  785. - AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
  786. - }
  787. + /* set the Audio InforFrame Channel Allocation */
  788. + snd_hda_codec_write(codec, 0x1, 0, Nv_VERB_SET_Channel_Allocation, chanmask);
  789.  
  790. - for (i = 0; i < 4; i++) {
  791. - if (chs == 2)
  792. - channel_id = 0;
  793. - else
  794. - channel_id = i * 2;
  795. -
  796. - /* turn off SPDIF once;
  797. - *otherwise the IEC958 bits won't be updated
  798. - */
  799. - if (codec->spdif_status_reset &&
  800. - (codec->spdif_ctls & AC_DIG1_ENABLE))
  801. - snd_hda_codec_write(codec,
  802. - nvhdmi_convert_nids[i],
  803. - 0,
  804. - AC_VERB_SET_DIGI_CONVERT_1,
  805. + if (codec->spdif_ctls & AC_DIG1_ENABLE)
  806. + snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
  807. codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
  808. +
  809. /* set the stream id */
  810. - snd_hda_codec_write(codec,
  811. - nvhdmi_convert_nids[i],
  812. - 0,
  813. - AC_VERB_SET_CHANNEL_STREAMID,
  814. - (stream_tag << 4) | channel_id);
  815. + snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
  816. /* set the stream format */
  817. - snd_hda_codec_write(codec,
  818. - nvhdmi_convert_nids[i],
  819. - 0,
  820. - AC_VERB_SET_STREAM_FORMAT,
  821. - format);
  822. - /* turn on again (if needed) */
  823. + snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
  824. /* enable and set the channel status audio/data flag */
  825. - if (codec->spdif_status_reset &&
  826. - (codec->spdif_ctls & AC_DIG1_ENABLE)) {
  827. - snd_hda_codec_write(codec,
  828. - nvhdmi_convert_nids[i],
  829. - 0,
  830. - AC_VERB_SET_DIGI_CONVERT_1,
  831. + if (codec->spdif_ctls & AC_DIG1_ENABLE)
  832. + snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
  833. + codec->spdif_ctls & 0xff);
  834. + /* enable and set the channel status audio/data flag */
  835. + snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0, AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
  836. +
  837. + for (i = 0; i < 4; i++)
  838. + {
  839. + if (chs == 2)
  840. + channel_id = 0;
  841. + else
  842. + channel_id = i * 2;
  843. +
  844. + if (codec->spdif_ctls & AC_DIG1_ENABLE)
  845. + snd_hda_codec_write(codec, nvhdmi_convert_nids_7x[i], 0, AC_VERB_SET_DIGI_CONVERT_1,
  846. + codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
  847. + /* set the stream id */
  848. + snd_hda_codec_write(codec, nvhdmi_convert_nids_7x[i], 0, AC_VERB_SET_CHANNEL_STREAMID,
  849. + (stream_tag << 4) | channel_id);
  850. + /* set the stream format */
  851. + snd_hda_codec_write(codec, nvhdmi_convert_nids_7x[i], 0, AC_VERB_SET_STREAM_FORMAT, format);
  852. + /* enable and set the channel status audio/data flag */
  853. + if (codec->spdif_ctls & AC_DIG1_ENABLE)
  854. + snd_hda_codec_write(codec, nvhdmi_convert_nids_7x[i], 0, AC_VERB_SET_DIGI_CONVERT_1,
  855. codec->spdif_ctls & 0xff);
  856. - snd_hda_codec_write(codec,
  857. - nvhdmi_convert_nids[i],
  858. - 0,
  859. - AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
  860. + /* enable and set the channel status audio/data flag */
  861. + snd_hda_codec_write(codec, nvhdmi_convert_nids_7x[i], 0, AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
  862. }
  863. - }
  864.  
  865. - /* set the Audio Info Frame Checksum */
  866. - snd_hda_codec_write(codec, 0x1, 0,
  867. - Nv_VERB_SET_Info_Frame_Checksum,
  868. - (0x71 - chan - chanmask));
  869. + /* set the Audio Info Frame Checksum */
  870. + snd_hda_codec_write(codec, 0x1, 0, Nv_VERB_SET_Info_Frame_Checksum, (0x71 - chan - chanmask));
  871.  
  872. - mutex_unlock(&codec->spdif_mutex);
  873. - return 0;
  874. -}
  875. -
  876. -static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
  877. - struct hda_codec *codec,
  878. - unsigned int stream_tag,
  879. - unsigned int format,
  880. - struct snd_pcm_substream *substream)
  881. -{
  882. - struct nvhdmi_spec *spec = codec->spec;
  883. - return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
  884. - format, substream);
  885. + mutex_unlock(&codec->spdif_mutex);
  886. + return 0;
  887. + }
  888. }
  889.  
  890. -static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = {
  891. +static struct hda_pcm_stream nvhdmi_pcm_digital_playback_89 = {
  892. .substreams = 1,
  893. .channels_min = 2,
  894. .channels_max = 8,
  895. - .nid = Nv_Master_Convert_nid,
  896. - .rates = SUPPORTED_RATES,
  897. - .maxbps = SUPPORTED_MAXBPS,
  898. - .formats = SUPPORTED_FORMATS,
  899. + .nid = nvhdmi_convert_nids_89,
  900. .ops = {
  901. .open = nvhdmi_dig_playback_pcm_open,
  902. - .close = nvhdmi_dig_playback_pcm_close_8ch,
  903. - .prepare = nvhdmi_dig_playback_pcm_prepare_8ch
  904. + .close = nvhdmi_dig_playback_pcm_close,
  905. + .prepare = nvhdmi_dig_playback_pcm_prepare
  906. },
  907. };
  908.  
  909. -static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
  910. +static struct hda_pcm_stream nvhdmi_pcm_digital_playback = {
  911. .substreams = 1,
  912. .channels_min = 2,
  913. - .channels_max = 2,
  914. - .nid = Nv_Master_Convert_nid,
  915. - .rates = SUPPORTED_RATES,
  916. - .maxbps = SUPPORTED_MAXBPS,
  917. - .formats = SUPPORTED_FORMATS,
  918. + .channels_max = 8,
  919. + .nid = Nv_Master_Convert_nid, /* NID to query formats and rates and setup streams */
  920. +// .rates = SNDRV_PCM_RATE_48000,
  921. +// .maxbps = 16,
  922. +// .formats = SNDRV_PCM_FMTBIT_S16_LE,
  923. .ops = {
  924. .open = nvhdmi_dig_playback_pcm_open,
  925. - .close = nvhdmi_dig_playback_pcm_close_2ch,
  926. - .prepare = nvhdmi_dig_playback_pcm_prepare_2ch
  927. + .close = nvhdmi_dig_playback_pcm_close,
  928. + .prepare = nvhdmi_dig_playback_pcm_prepare
  929. },
  930. };
  931.  
  932. -static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
  933. +static int nvhdmi_build_pcms(struct hda_codec *codec)
  934. {
  935. struct nvhdmi_spec *spec = codec->spec;
  936. struct hda_pcm *info = &spec->pcm_rec;
  937. @@ -312,24 +796,16 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
  938.  
  939. info->name = "NVIDIA HDMI";
  940. info->pcm_type = HDA_PCM_TYPE_HDMI;
  941. - info->stream[SNDRV_PCM_STREAM_PLAYBACK]
  942. - = nvhdmi_pcm_digital_playback_8ch;
  943.  
  944. - return 0;
  945. -}
  946. -
  947. -static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
  948. -{
  949. - struct nvhdmi_spec *spec = codec->spec;
  950. - struct hda_pcm *info = &spec->pcm_rec;
  951. -
  952. - codec->num_pcms = 1;
  953. - codec->pcm_info = info;
  954. -
  955. - info->name = "NVIDIA HDMI";
  956. - info->pcm_type = HDA_PCM_TYPE_HDMI;
  957. - info->stream[SNDRV_PCM_STREAM_PLAYBACK]
  958. - = nvhdmi_pcm_digital_playback_2ch;
  959. + if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
  960. + || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X))
  961. + {
  962. + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = nvhdmi_pcm_digital_playback_89;
  963. + }
  964. + else
  965. + {
  966. + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = nvhdmi_pcm_digital_playback;
  967. + }
  968.  
  969. return 0;
  970. }
  971. @@ -339,21 +815,14 @@ static void nvhdmi_free(struct hda_codec *codec)
  972. kfree(codec->spec);
  973. }
  974.  
  975. -static struct hda_codec_ops nvhdmi_patch_ops_8ch = {
  976. +static struct hda_codec_ops nvhdmi_patch_ops = {
  977. .build_controls = nvhdmi_build_controls,
  978. - .build_pcms = nvhdmi_build_pcms_8ch,
  979. + .build_pcms = nvhdmi_build_pcms,
  980. .init = nvhdmi_init,
  981. .free = nvhdmi_free,
  982. };
  983.  
  984. -static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
  985. - .build_controls = nvhdmi_build_controls,
  986. - .build_pcms = nvhdmi_build_pcms_2ch,
  987. - .init = nvhdmi_init,
  988. - .free = nvhdmi_free,
  989. -};
  990. -
  991. -static int patch_nvhdmi_8ch(struct hda_codec *codec)
  992. +static int patch_nvhdmi(struct hda_codec *codec)
  993. {
  994. struct nvhdmi_spec *spec;
  995.  
  996. @@ -367,26 +836,21 @@ static int patch_nvhdmi_8ch(struct hda_codec *codec)
  997. spec->multiout.max_channels = 8;
  998. spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
  999.  
  1000. - codec->patch_ops = nvhdmi_patch_ops_8ch;
  1001. -
  1002. - return 0;
  1003. -}
  1004. -
  1005. -static int patch_nvhdmi_2ch(struct hda_codec *codec)
  1006. -{
  1007. - struct nvhdmi_spec *spec;
  1008. -
  1009. - spec = kzalloc(sizeof(*spec), GFP_KERNEL);
  1010. - if (spec == NULL)
  1011. - return -ENOMEM;
  1012. -
  1013. - codec->spec = spec;
  1014. -
  1015. - spec->multiout.num_dacs = 0; /* no analog */
  1016. - spec->multiout.max_channels = 2;
  1017. - spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
  1018. + switch (codec->vendor_id) {
  1019. + case 0x10de000c:
  1020. + spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
  1021. + break;
  1022. + case 0x10de000d:
  1023. + case 0x10de000a:
  1024. + case 0x10de000b:
  1025. + spec->codec_type = HDA_CODEC_NVIDIA_GT21X;
  1026. + break;
  1027. + default:
  1028. + spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
  1029. + break;
  1030. + }
  1031.  
  1032. - codec->patch_ops = nvhdmi_patch_ops_2ch;
  1033. + codec->patch_ops = nvhdmi_patch_ops;
  1034.  
  1035. return 0;
  1036. }
  1037. @@ -394,41 +858,41 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
  1038. /*
  1039. * patch entries
  1040. */
  1041. -static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
  1042. - { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
  1043. - { .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
  1044. - { .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
  1045. - { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
  1046. - { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch },
  1047. - { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
  1048. - { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
  1049. +struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
  1050. + { .id = 0x10de0002, .name = "NVIDIA MCP77/78 HDMI", .patch = patch_nvhdmi },
  1051. + { .id = 0x10de0007, .name = "NVIDIA MCP79/7A HDMI", .patch = patch_nvhdmi },
  1052. + { .id = 0x10de8001, .name = "NVIDIA MCP73 HDMI", .patch = patch_nvhdmi },
  1053. + { .id = 0x10de000c, .name = "NVIDIA MCP89 HDMI", .patch = patch_nvhdmi },
  1054. + { .id = 0x10de000d, .name = "NVIDIA GT240 HDMI", .patch = patch_nvhdmi },
  1055. + { .id = 0x10de000a, .name = "NVIDIA GT220 HDMI", .patch = patch_nvhdmi },
  1056. + { .id = 0x10de000b, .name = "NVIDIA G210 HDMI", .patch = patch_nvhdmi },
  1057. {} /* terminator */
  1058. };
  1059.  
  1060. MODULE_ALIAS("snd-hda-codec-id:10de0002");
  1061. -MODULE_ALIAS("snd-hda-codec-id:10de0003");
  1062. -MODULE_ALIAS("snd-hda-codec-id:10de0005");
  1063. -MODULE_ALIAS("snd-hda-codec-id:10de0006");
  1064. MODULE_ALIAS("snd-hda-codec-id:10de0007");
  1065. -MODULE_ALIAS("snd-hda-codec-id:10de0067");
  1066. MODULE_ALIAS("snd-hda-codec-id:10de8001");
  1067. +MODULE_ALIAS("snd-hda-codec-id:10de000c");
  1068. +MODULE_ALIAS("snd-hda-codec-id:10de000d");
  1069. +MODULE_ALIAS("snd-hda-codec-id:10de000a");
  1070. +MODULE_ALIAS("snd-hda-codec-id:10de000b");
  1071.  
  1072. MODULE_LICENSE("GPL");
  1073. -MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec");
  1074. +MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec");
  1075.  
  1076. static struct hda_codec_preset_list nvhdmi_list = {
  1077. - .preset = snd_hda_preset_nvhdmi,
  1078. - .owner = THIS_MODULE,
  1079. + .preset = snd_hda_preset_nvhdmi,
  1080. + .owner = THIS_MODULE,
  1081. };
  1082.  
  1083. static int __init patch_nvhdmi_init(void)
  1084. {
  1085. - return snd_hda_add_codec_preset(&nvhdmi_list);
  1086. + return snd_hda_add_codec_preset(&nvhdmi_list);
  1087. }
  1088.  
  1089. static void __exit patch_nvhdmi_exit(void)
  1090. {
  1091. - snd_hda_delete_codec_preset(&nvhdmi_list);
  1092. + snd_hda_delete_codec_preset(&nvhdmi_list);
  1093. }
  1094.  
  1095. module_init(patch_nvhdmi_init)
  1096.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement