Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'soundwire-6.19-rc1_updated' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire

Pull soundwire updates from Vinod Koul:

- Support for multiple sections in a BPT stream

- Align DMA frame with BPT frames

- Qualcomm support for v3.1.0 controllers

* tag 'soundwire-6.19-rc1_updated' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire:
soundwire: intel_ace2x: handle multi BPT sections
soundwire: pass sdw_bpt_section to cdns BPT helpers
soundwire: introduce BPT section
soundwire: intel_ace2x: add fake frame to BRA read command
soundwire: cadence_master: add fake_size parameter to sdw_cdns_prepare_read_dma_buffer
ASoC: SOF: Intel: export hda_sdw_bpt_get_buf_size_aligment
soundwire: cadence: export sdw_cdns_bpt_find_bandwidth
soundwire: cadence_master: set data_per_frame as frame capability
soundwire: only compute BPT stream in sdw_compute_dp0_port_params
soundwire: cadence_master: make frame index trace more readable
soundwire: qcom: adding support for v3.1.0
dt-bindings: soundwire: qcom: Document v3.1.0 version of IP block
soundwire: qcom: prepare for v3.x
soundwire: qcom: deprecate qcom,din/out-ports
dt-bindings: soundwire: qcom: deprecate qcom,din/out-ports
soundwire: qcom: remove unused rd_fifo_depth
of: base: Add of_property_read_u8_index

+530 -206
+3 -5
Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml
··· 23 23 - qcom,soundwire-v1.6.0 24 24 - qcom,soundwire-v1.7.0 25 25 - qcom,soundwire-v2.0.0 26 + - qcom,soundwire-v3.1.0 26 27 - items: 27 28 - enum: 28 29 - qcom,soundwire-v2.1.0 ··· 74 73 qcom,din-ports: 75 74 $ref: /schemas/types.yaml#/definitions/uint32 76 75 description: count of data in ports 76 + deprecated: true 77 77 78 78 qcom,dout-ports: 79 79 $ref: /schemas/types.yaml#/definitions/uint32 80 80 description: count of data out ports 81 + deprecated: true 81 82 82 83 qcom,ports-word-length: 83 84 $ref: /schemas/types.yaml#/definitions/uint8-array ··· 226 223 - '#sound-dai-cells' 227 224 - '#address-cells' 228 225 - '#size-cells' 229 - - qcom,dout-ports 230 - - qcom,din-ports 231 226 - qcom,ports-offset1 232 227 - qcom,ports-offset2 233 228 ··· 257 256 258 257 clocks = <&lpass_rx_macro>; 259 258 clock-names = "iface"; 260 - 261 - qcom,din-ports = <0>; 262 - qcom,dout-ports = <5>; 263 259 264 260 resets = <&lpass_audiocc LPASS_AUDIO_SWR_RX_CGCR>; 265 261 reset-names = "swr_audio_cgcr";
+33
drivers/of/property.c
··· 148 148 } 149 149 150 150 /** 151 + * of_property_read_u8_index - Find and read a u8 from a multi-value property. 152 + * 153 + * @np: device node from which the property value is to be read. 154 + * @propname: name of the property to be searched. 155 + * @index: index of the u8 in the list of values 156 + * @out_value: pointer to return value, modified only if no error. 157 + * 158 + * Search for a property in a device node and read nth 8-bit value from 159 + * it. 160 + * 161 + * Return: 0 on success, -EINVAL if the property does not exist, 162 + * -ENODATA if property does not have a value, and -EOVERFLOW if the 163 + * property data isn't large enough. 164 + * 165 + * The out_value is modified only if a valid u8 value can be decoded. 166 + */ 167 + int of_property_read_u8_index(const struct device_node *np, 168 + const char *propname, 169 + u32 index, u8 *out_value) 170 + { 171 + const u8 *val = of_find_property_value_of_size(np, propname, 172 + ((index + 1) * sizeof(*out_value)), 173 + 0, NULL); 174 + 175 + if (IS_ERR(val)) 176 + return PTR_ERR(val); 177 + 178 + *out_value = val[index]; 179 + return 0; 180 + } 181 + EXPORT_SYMBOL_GPL(of_property_read_u8_index); 182 + 183 + /** 151 184 * of_property_read_u16_index - Find and read a u16 from a multi-value property. 152 185 * 153 186 * @np: device node from which the property value is to be read.
+8 -2
drivers/soundwire/bus.c
··· 2052 2052 2053 2053 int sdw_bpt_send_async(struct sdw_bus *bus, struct sdw_slave *slave, struct sdw_bpt_msg *msg) 2054 2054 { 2055 - if (msg->len > SDW_BPT_MSG_MAX_BYTES) { 2056 - dev_err(bus->dev, "Invalid BPT message length %d\n", msg->len); 2055 + int len = 0; 2056 + int i; 2057 + 2058 + for (i = 0; i < msg->sections; i++) 2059 + len += msg->sec[i].len; 2060 + 2061 + if (len > SDW_BPT_MSG_MAX_BYTES) { 2062 + dev_err(bus->dev, "Invalid BPT message length %d\n", len); 2057 2063 return -EINVAL; 2058 2064 } 2059 2065
+16 -6
drivers/soundwire/bus.h
··· 73 73 }; 74 74 75 75 /** 76 - * struct sdw_btp_msg - Message structure 76 + * struct sdw_btp_section - Message section structure 77 77 * @addr: Start Register address accessed in the Slave 78 78 * @len: number of bytes to transfer. More than 64Kb can be transferred 79 79 * but a practical limit of SDW_BPT_MSG_MAX_BYTES is enforced. 80 - * @dev_num: Slave device number 81 - * @flags: transfer flags, indicate if xfer is read or write 82 - * @buf: message data buffer (filled by host for write, filled 80 + * @buf: section data buffer (filled by host for write, filled 83 81 * by Peripheral hardware for reads) 84 82 */ 85 - struct sdw_bpt_msg { 83 + struct sdw_bpt_section { 86 84 u32 addr; 87 85 u32 len; 86 + u8 *buf; 87 + }; 88 + 89 + /** 90 + * struct sdw_btp_msg - Message structure 91 + * @sec: Pointer to array of sections 92 + * @sections: Number of sections in the array 93 + * @dev_num: Slave device number 94 + * @flags: transfer flags, indicate if xfer is read or write 95 + */ 96 + struct sdw_bpt_msg { 97 + struct sdw_bpt_section *sec; 98 + int sections; 88 99 u8 dev_num; 89 100 u8 flags; 90 - u8 *buf; 91 101 }; 92 102 93 103 #define SDW_DOUBLE_RATE_FACTOR 2
+171 -66
drivers/soundwire/cadence_master.c
··· 2094 2094 return total * 2; 2095 2095 } 2096 2096 2097 + int sdw_cdns_bpt_find_bandwidth(int command, /* 0: write, 1: read */ 2098 + int row, int col, int frame_rate, 2099 + unsigned int *tx_dma_bandwidth, 2100 + unsigned int *rx_dma_bandwidth) 2101 + { 2102 + unsigned int bpt_bits = row * (col - 1); 2103 + unsigned int bpt_bytes = bpt_bits >> 3; 2104 + unsigned int pdi0_buffer_size; 2105 + unsigned int pdi1_buffer_size; 2106 + unsigned int data_per_frame; 2107 + 2108 + data_per_frame = sdw_cdns_bra_actual_data_size(bpt_bytes); 2109 + if (!data_per_frame) 2110 + return -EINVAL; 2111 + 2112 + if (command == 0) { 2113 + pdi0_buffer_size = sdw_cdns_write_pdi0_buffer_size(data_per_frame); 2114 + pdi1_buffer_size = SDW_CDNS_WRITE_PDI1_BUFFER_SIZE; 2115 + } else { 2116 + pdi0_buffer_size = SDW_CDNS_READ_PDI0_BUFFER_SIZE; 2117 + pdi1_buffer_size = sdw_cdns_read_pdi1_buffer_size(data_per_frame); 2118 + } 2119 + 2120 + *tx_dma_bandwidth = pdi0_buffer_size * 8 * frame_rate; 2121 + *rx_dma_bandwidth = pdi1_buffer_size * 8 * frame_rate; 2122 + 2123 + return 0; 2124 + } 2125 + EXPORT_SYMBOL(sdw_cdns_bpt_find_bandwidth); 2126 + 2097 2127 int sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */ 2098 2128 int row, int col, unsigned int data_bytes, 2099 2129 unsigned int requested_bytes_per_frame, ··· 2144 2114 if (!actual_bpt_bytes) 2145 2115 return -EINVAL; 2146 2116 2147 - if (data_bytes < actual_bpt_bytes) 2148 - actual_bpt_bytes = data_bytes; 2149 - 2150 2117 /* 2151 2118 * the caller may want to set the number of bytes per frame, 2152 2119 * allow when possible ··· 2152 2125 actual_bpt_bytes = requested_bytes_per_frame; 2153 2126 2154 2127 *data_per_frame = actual_bpt_bytes; 2128 + 2129 + if (data_bytes < actual_bpt_bytes) 2130 + actual_bpt_bytes = data_bytes; 2155 2131 2156 2132 if (command == 0) { 2157 2133 /* ··· 2324 2294 2325 2295 #define CDNS_BPT_ROLLING_COUNTER_START 1 2326 2296 2327 - int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data, int data_size, 2328 - int data_per_frame, u8 *dma_buffer, int dma_buffer_size, 2329 - int *dma_buffer_total_bytes) 2297 + int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec, 2298 + int data_per_frame, u8 *dma_buffer, 2299 + int dma_buffer_size, int *dma_buffer_total_bytes) 2330 2300 { 2331 2301 int total_dma_data_written = 0; 2332 2302 u8 *p_dma_buffer = dma_buffer; 2333 2303 u8 header[SDW_CDNS_BRA_HDR]; 2304 + unsigned int start_register; 2305 + unsigned int section_size; 2334 2306 int dma_data_written; 2335 - u8 *p_data = data; 2307 + u8 *p_data; 2336 2308 u8 counter; 2337 2309 int ret; 2310 + int i; 2338 2311 2339 2312 counter = CDNS_BPT_ROLLING_COUNTER_START; 2340 2313 ··· 2345 2312 header[0] |= GENMASK(7, 6); /* header is active */ 2346 2313 header[0] |= (dev_num << 2); 2347 2314 2348 - while (data_size >= data_per_frame) { 2349 - header[1] = data_per_frame; 2350 - header[2] = start_register >> 24 & 0xFF; 2351 - header[3] = start_register >> 16 & 0xFF; 2352 - header[4] = start_register >> 8 & 0xFF; 2353 - header[5] = start_register >> 0 & 0xFF; 2315 + for (i = 0; i < num_sec; i++) { 2316 + start_register = sec[i].addr; 2317 + section_size = sec[i].len; 2318 + p_data = sec[i].buf; 2354 2319 2355 - ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR, 2356 - p_data, data_per_frame, 2357 - p_dma_buffer, dma_buffer_size, 2358 - &dma_data_written, counter); 2359 - if (ret < 0) 2360 - return ret; 2320 + while (section_size >= data_per_frame) { 2321 + header[1] = data_per_frame; 2322 + header[2] = start_register >> 24 & 0xFF; 2323 + header[3] = start_register >> 16 & 0xFF; 2324 + header[4] = start_register >> 8 & 0xFF; 2325 + header[5] = start_register >> 0 & 0xFF; 2361 2326 2362 - counter++; 2327 + ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR, 2328 + p_data, data_per_frame, 2329 + p_dma_buffer, dma_buffer_size, 2330 + &dma_data_written, counter); 2331 + if (ret < 0) 2332 + return ret; 2363 2333 2364 - p_data += data_per_frame; 2365 - data_size -= data_per_frame; 2334 + counter++; 2366 2335 2367 - p_dma_buffer += dma_data_written; 2368 - dma_buffer_size -= dma_data_written; 2369 - total_dma_data_written += dma_data_written; 2336 + p_data += data_per_frame; 2337 + section_size -= data_per_frame; 2370 2338 2371 - start_register += data_per_frame; 2372 - } 2339 + p_dma_buffer += dma_data_written; 2340 + dma_buffer_size -= dma_data_written; 2341 + total_dma_data_written += dma_data_written; 2373 2342 2374 - if (data_size) { 2375 - header[1] = data_size; 2376 - header[2] = start_register >> 24 & 0xFF; 2377 - header[3] = start_register >> 16 & 0xFF; 2378 - header[4] = start_register >> 8 & 0xFF; 2379 - header[5] = start_register >> 0 & 0xFF; 2343 + start_register += data_per_frame; 2344 + } 2380 2345 2381 - ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR, 2382 - p_data, data_size, 2383 - p_dma_buffer, dma_buffer_size, 2384 - &dma_data_written, counter); 2385 - if (ret < 0) 2386 - return ret; 2346 + if (section_size) { 2347 + header[1] = section_size; 2348 + header[2] = start_register >> 24 & 0xFF; 2349 + header[3] = start_register >> 16 & 0xFF; 2350 + header[4] = start_register >> 8 & 0xFF; 2351 + header[5] = start_register >> 0 & 0xFF; 2387 2352 2388 - total_dma_data_written += dma_data_written; 2353 + ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR, 2354 + p_data, section_size, 2355 + p_dma_buffer, dma_buffer_size, 2356 + &dma_data_written, counter); 2357 + if (ret < 0) 2358 + return ret; 2359 + 2360 + counter++; 2361 + 2362 + p_dma_buffer += dma_data_written; 2363 + dma_buffer_size -= dma_data_written; 2364 + total_dma_data_written += dma_data_written; 2365 + } 2389 2366 } 2390 2367 2391 2368 *dma_buffer_total_bytes = total_dma_data_written; ··· 2404 2361 } 2405 2362 EXPORT_SYMBOL(sdw_cdns_prepare_write_dma_buffer); 2406 2363 2407 - int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_size, 2364 + int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec, 2408 2365 int data_per_frame, u8 *dma_buffer, int dma_buffer_size, 2409 - int *dma_buffer_total_bytes) 2366 + int *dma_buffer_total_bytes, unsigned int fake_size) 2410 2367 { 2411 2368 int total_dma_data_written = 0; 2412 2369 u8 *p_dma_buffer = dma_buffer; 2413 2370 u8 header[SDW_CDNS_BRA_HDR]; 2371 + unsigned int start_register; 2372 + unsigned int data_size; 2414 2373 int dma_data_written; 2415 2374 u8 counter; 2416 2375 int ret; 2376 + int i; 2417 2377 2418 2378 counter = CDNS_BPT_ROLLING_COUNTER_START; 2419 2379 ··· 2424 2378 header[0] |= GENMASK(7, 6); /* header is active */ 2425 2379 header[0] |= (dev_num << 2); 2426 2380 2427 - while (data_size >= data_per_frame) { 2428 - header[1] = data_per_frame; 2429 - header[2] = start_register >> 24 & 0xFF; 2430 - header[3] = start_register >> 16 & 0xFF; 2431 - header[4] = start_register >> 8 & 0xFF; 2432 - header[5] = start_register >> 0 & 0xFF; 2381 + for (i = 0; i < num_sec; i++) { 2382 + start_register = sec[i].addr; 2383 + data_size = sec[i].len; 2384 + while (data_size >= data_per_frame) { 2385 + header[1] = data_per_frame; 2386 + header[2] = start_register >> 24 & 0xFF; 2387 + header[3] = start_register >> 16 & 0xFF; 2388 + header[4] = start_register >> 8 & 0xFF; 2389 + header[5] = start_register >> 0 & 0xFF; 2433 2390 2391 + ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, 2392 + p_dma_buffer, dma_buffer_size, 2393 + &dma_data_written, counter); 2394 + if (ret < 0) 2395 + return ret; 2396 + 2397 + counter++; 2398 + 2399 + data_size -= data_per_frame; 2400 + 2401 + p_dma_buffer += dma_data_written; 2402 + dma_buffer_size -= dma_data_written; 2403 + total_dma_data_written += dma_data_written; 2404 + 2405 + start_register += data_per_frame; 2406 + } 2407 + 2408 + if (data_size) { 2409 + header[1] = data_size; 2410 + header[2] = start_register >> 24 & 0xFF; 2411 + header[3] = start_register >> 16 & 0xFF; 2412 + header[4] = start_register >> 8 & 0xFF; 2413 + header[5] = start_register >> 0 & 0xFF; 2414 + 2415 + ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, 2416 + p_dma_buffer, dma_buffer_size, 2417 + &dma_data_written, counter); 2418 + if (ret < 0) 2419 + return ret; 2420 + 2421 + counter++; 2422 + 2423 + p_dma_buffer += dma_data_written; 2424 + dma_buffer_size -= dma_data_written; 2425 + total_dma_data_written += dma_data_written; 2426 + } 2427 + } 2428 + 2429 + /* Add fake frame */ 2430 + header[0] &= ~GENMASK(7, 6); /* Set inactive flag in BPT/BRA frame heade */ 2431 + while (fake_size >= data_per_frame) { 2432 + header[1] = data_per_frame; 2434 2433 ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, p_dma_buffer, 2435 2434 dma_buffer_size, &dma_data_written, 2436 2435 counter); ··· 2484 2393 2485 2394 counter++; 2486 2395 2487 - data_size -= data_per_frame; 2488 - 2396 + fake_size -= data_per_frame; 2489 2397 p_dma_buffer += dma_data_written; 2490 2398 dma_buffer_size -= dma_data_written; 2491 2399 total_dma_data_written += dma_data_written; 2492 - 2493 - start_register += data_per_frame; 2494 2400 } 2495 2401 2496 - if (data_size) { 2497 - header[1] = data_size; 2498 - header[2] = start_register >> 24 & 0xFF; 2499 - header[3] = start_register >> 16 & 0xFF; 2500 - header[4] = start_register >> 8 & 0xFF; 2501 - header[5] = start_register >> 0 & 0xFF; 2502 - 2402 + if (fake_size) { 2403 + header[1] = fake_size; 2503 2404 ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, p_dma_buffer, 2504 2405 dma_buffer_size, &dma_data_written, 2505 2406 counter); 2506 2407 if (ret < 0) 2507 2408 return ret; 2508 2409 2410 + counter++; 2411 + 2412 + p_dma_buffer += dma_data_written; 2413 + dma_buffer_size -= dma_data_written; 2509 2414 total_dma_data_written += dma_data_written; 2510 2415 } 2511 2416 ··· 2582 2495 ret = check_frame_start(header, counter); 2583 2496 if (ret < 0) { 2584 2497 dev_err(dev, "%s: bad frame %d/%d start header %x\n", 2585 - __func__, i, num_frames, header); 2498 + __func__, i + 1, num_frames, header); 2586 2499 return ret; 2587 2500 } 2588 2501 2589 2502 ret = check_frame_end(footer); 2590 2503 if (ret < 0) { 2591 2504 dev_err(dev, "%s: bad frame %d/%d end footer %x\n", 2592 - __func__, i, num_frames, footer); 2505 + __func__, i + 1, num_frames, footer); 2593 2506 return ret; 2594 2507 } 2595 2508 ··· 2636 2549 } 2637 2550 2638 2551 int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buffer_size, 2639 - u8 *buffer, int buffer_size, int num_frames, int data_per_frame) 2552 + struct sdw_bpt_section *sec, int num_sec, int num_frames, 2553 + int data_per_frame) 2640 2554 { 2641 2555 int total_num_bytes = 0; 2556 + int buffer_size = 0; 2557 + int sec_index; 2642 2558 u32 *p_data; 2643 2559 u8 *p_buf; 2644 2560 int counter; ··· 2655 2565 2656 2566 counter = CDNS_BPT_ROLLING_COUNTER_START; 2657 2567 p_data = (u32 *)dma_buffer; 2658 - p_buf = buffer; 2568 + 2569 + sec_index = 0; 2570 + p_buf = sec[sec_index].buf; 2571 + buffer_size = sec[sec_index].len; 2659 2572 2660 2573 for (i = 0; i < num_frames; i++) { 2661 2574 header = *p_data++; ··· 2666 2573 ret = check_frame_start(header, counter); 2667 2574 if (ret < 0) { 2668 2575 dev_err(dev, "%s: bad frame %d/%d start header %x\n", 2669 - __func__, i, num_frames, header); 2576 + __func__, i + 1, num_frames, header); 2670 2577 return ret; 2671 2578 } 2672 2579 ··· 2681 2588 2682 2589 if (crc != expected_crc) { 2683 2590 dev_err(dev, "%s: bad frame %d/%d crc %#x expected %#x\n", 2684 - __func__, i, num_frames, crc, expected_crc); 2591 + __func__, i + 1, num_frames, crc, expected_crc); 2685 2592 return -EIO; 2686 2593 } 2687 2594 ··· 2692 2599 ret = check_frame_end(footer); 2693 2600 if (ret < 0) { 2694 2601 dev_err(dev, "%s: bad frame %d/%d end footer %x\n", 2695 - __func__, i, num_frames, footer); 2602 + __func__, i + 1, num_frames, footer); 2696 2603 return ret; 2697 2604 } 2698 2605 2699 2606 counter++; 2700 2607 counter &= GENMASK(3, 0); 2608 + 2609 + if (buffer_size == total_num_bytes && (i + 1) < num_frames) { 2610 + sec_index++; 2611 + if (sec_index >= num_sec) { 2612 + dev_err(dev, "%s: incorrect section index %d i %d\n", 2613 + __func__, sec_index, i); 2614 + return -EINVAL; 2615 + } 2616 + p_buf = sec[sec_index].buf; 2617 + buffer_size = sec[sec_index].len; 2618 + total_num_bytes = 0; 2619 + } 2701 2620 } 2702 2621 return 0; 2703 2622 }
+13 -6
drivers/soundwire/cadence_master.h
··· 1 1 /* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ 2 2 /* Copyright(c) 2015-17 Intel Corporation. */ 3 3 #include <sound/soc.h> 4 + #include "bus.h" 4 5 5 6 #ifndef __SDW_CADENCE_H 6 7 #define __SDW_CADENCE_H ··· 210 209 int sdw_cdns_config_update_set_wait(struct sdw_cdns *cdns); 211 210 212 211 /* SoundWire BPT/BRA helpers to format data */ 212 + int sdw_cdns_bpt_find_bandwidth(int command, /* 0: write, 1: read */ 213 + int row, int col, int frame_rate, 214 + unsigned int *tx_dma_bandwidth, 215 + unsigned int *rx_dma_bandwidth); 216 + 213 217 int sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */ 214 218 int row, int col, unsigned int data_bytes, 215 219 unsigned int requested_bytes_per_frame, 216 220 unsigned int *data_per_frame, unsigned int *pdi0_buffer_size, 217 221 unsigned int *pdi1_buffer_size, unsigned int *num_frames); 218 222 219 - int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data, int data_size, 220 - int data_per_frame, u8 *dma_buffer, int dma_buffer_size, 221 - int *dma_buffer_total_bytes); 223 + int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec, 224 + int data_per_frame, u8 *dma_buffer, 225 + int dma_buffer_size, int *dma_buffer_total_bytes); 222 226 223 - int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_size, 227 + int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec, 224 228 int data_per_frame, u8 *dma_buffer, int dma_buffer_size, 225 - int *dma_buffer_total_bytes); 229 + int *dma_buffer_total_bytes, unsigned int fake_size); 226 230 227 231 int sdw_cdns_check_write_response(struct device *dev, u8 *dma_buffer, 228 232 int dma_buffer_size, int num_frames); 229 233 230 234 int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buffer_size, 231 - u8 *buffer, int buffer_size, int num_frames, int data_per_frame); 235 + struct sdw_bpt_section *sec, int num_sec, int num_frames, 236 + int data_per_frame); 232 237 #endif /* __SDW_CADENCE_H */
+11 -3
drivers/soundwire/debugfs.c
··· 222 222 static int do_bpt_sequence(struct sdw_slave *slave, bool write, u8 *buffer) 223 223 { 224 224 struct sdw_bpt_msg msg = {0}; 225 + struct sdw_bpt_section *sec; 225 226 226 - msg.addr = start_addr; 227 - msg.len = num_bytes; 227 + sec = kcalloc(1, sizeof(*sec), GFP_KERNEL); 228 + if (!sec) 229 + return -ENOMEM; 230 + msg.sections = 1; 231 + 232 + sec[0].addr = start_addr; 233 + sec[0].len = num_bytes; 234 + 235 + msg.sec = sec; 228 236 msg.dev_num = slave->dev_num; 229 237 if (write) 230 238 msg.flags = SDW_MSG_FLAG_WRITE; 231 239 else 232 240 msg.flags = SDW_MSG_FLAG_READ; 233 - msg.buf = buffer; 241 + sec[0].buf = buffer; 234 242 235 243 return sdw_bpt_send_sync(slave->bus, slave, &msg); 236 244 }
+3
drivers/soundwire/generic_bandwidth_allocation.c
··· 124 124 struct sdw_master_runtime *m_rt; 125 125 126 126 list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) { 127 + /* DP0 is for BPT only */ 128 + if (m_rt->stream->type != SDW_STREAM_BPT) 129 + continue; 127 130 sdw_compute_dp0_master_ports(m_rt); 128 131 sdw_compute_dp0_slave_ports(m_rt); 129 132 }
+89 -15
drivers/soundwire/intel_ace2x.c
··· 44 44 return ret; 45 45 } 46 46 47 + #define READ_PDI1_MIN_SIZE 12 48 + 47 49 static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *slave, 48 50 struct sdw_bpt_msg *msg) 49 51 { ··· 55 53 struct sdw_stream_runtime *stream; 56 54 struct sdw_stream_config sconfig; 57 55 struct sdw_port_config *pconfig; 56 + unsigned int pdi0_buf_size_pre_frame; 57 + unsigned int pdi1_buf_size_pre_frame; 58 + unsigned int pdi0_buffer_size_; 59 + unsigned int pdi1_buffer_size_; 58 60 unsigned int pdi0_buffer_size; 59 61 unsigned int tx_dma_bandwidth; 60 62 unsigned int pdi1_buffer_size; 61 63 unsigned int rx_dma_bandwidth; 64 + unsigned int fake_num_frames; 62 65 unsigned int data_per_frame; 63 66 unsigned int tx_total_bytes; 64 67 struct sdw_cdns_pdi *pdi0; 65 68 struct sdw_cdns_pdi *pdi1; 69 + unsigned int rx_alignment; 70 + unsigned int tx_alignment; 71 + unsigned int num_frames_; 66 72 unsigned int num_frames; 73 + unsigned int fake_size; 74 + unsigned int tx_pad; 75 + unsigned int rx_pad; 67 76 int command; 68 77 int ret1; 69 78 int ret; 70 79 int dir; 80 + int len; 71 81 int i; 72 82 73 83 stream = sdw_alloc_stream("BPT", SDW_STREAM_BPT); ··· 152 138 153 139 command = (msg->flags & SDW_MSG_FLAG_WRITE) ? 0 : 1; 154 140 155 - ret = sdw_cdns_bpt_find_buffer_sizes(command, cdns->bus.params.row, cdns->bus.params.col, 156 - msg->len, SDW_BPT_MSG_MAX_BYTES, &data_per_frame, 157 - &pdi0_buffer_size, &pdi1_buffer_size, &num_frames); 141 + ret = sdw_cdns_bpt_find_bandwidth(command, cdns->bus.params.row, 142 + cdns->bus.params.col, 143 + prop->default_frame_rate, 144 + &tx_dma_bandwidth, &rx_dma_bandwidth); 158 145 if (ret < 0) 159 146 goto deprepare_stream; 147 + 148 + len = 0; 149 + pdi0_buffer_size = 0; 150 + pdi1_buffer_size = 0; 151 + num_frames = 0; 152 + /* Add up pdi buffer size and frame numbers of each BPT sections */ 153 + for (i = 0; i < msg->sections; i++) { 154 + ret = sdw_cdns_bpt_find_buffer_sizes(command, cdns->bus.params.row, 155 + cdns->bus.params.col, 156 + msg->sec[i].len, SDW_BPT_MSG_MAX_BYTES, 157 + &data_per_frame, &pdi0_buffer_size_, 158 + &pdi1_buffer_size_, &num_frames_); 159 + if (ret < 0) 160 + goto deprepare_stream; 161 + 162 + len += msg->sec[i].len; 163 + pdi0_buffer_size += pdi0_buffer_size_; 164 + pdi1_buffer_size += pdi1_buffer_size_; 165 + num_frames += num_frames_; 166 + } 160 167 161 168 sdw->bpt_ctx.pdi0_buffer_size = pdi0_buffer_size; 162 169 sdw->bpt_ctx.pdi1_buffer_size = pdi1_buffer_size; 163 170 sdw->bpt_ctx.num_frames = num_frames; 164 171 sdw->bpt_ctx.data_per_frame = data_per_frame; 165 - tx_dma_bandwidth = div_u64((u64)pdi0_buffer_size * 8 * (u64)prop->default_frame_rate, 166 - num_frames); 167 - rx_dma_bandwidth = div_u64((u64)pdi1_buffer_size * 8 * (u64)prop->default_frame_rate, 168 - num_frames); 172 + 173 + rx_alignment = hda_sdw_bpt_get_buf_size_alignment(rx_dma_bandwidth); 174 + tx_alignment = hda_sdw_bpt_get_buf_size_alignment(tx_dma_bandwidth); 175 + 176 + if (command) { /* read */ 177 + /* Get buffer size of a full frame */ 178 + ret = sdw_cdns_bpt_find_buffer_sizes(command, cdns->bus.params.row, 179 + cdns->bus.params.col, 180 + data_per_frame, SDW_BPT_MSG_MAX_BYTES, 181 + &data_per_frame, &pdi0_buf_size_pre_frame, 182 + &pdi1_buf_size_pre_frame, &fake_num_frames); 183 + if (ret < 0) 184 + goto deprepare_stream; 185 + 186 + /* find fake pdi1 buffer size */ 187 + rx_pad = rx_alignment - (pdi1_buffer_size % rx_alignment); 188 + while (rx_pad <= READ_PDI1_MIN_SIZE) 189 + rx_pad += rx_alignment; 190 + 191 + pdi1_buffer_size += rx_pad; 192 + /* It is fine if we request more than enough byte to read */ 193 + fake_num_frames = DIV_ROUND_UP(rx_pad, pdi1_buf_size_pre_frame); 194 + fake_size = fake_num_frames * data_per_frame; 195 + 196 + /* find fake pdi0 buffer size */ 197 + pdi0_buffer_size += (fake_num_frames * pdi0_buf_size_pre_frame); 198 + tx_pad = tx_alignment - (pdi0_buffer_size % tx_alignment); 199 + pdi0_buffer_size += tx_pad; 200 + } else { /* write */ 201 + /* 202 + * For the write command, the rx data block is 4, and the rx buffer size of a frame 203 + * is 8. So the rx buffer size (pdi0_buffer_size) is always a multiple of rx 204 + * alignment. 205 + */ 206 + tx_pad = tx_alignment - (pdi0_buffer_size % tx_alignment); 207 + pdi0_buffer_size += tx_pad; 208 + } 169 209 170 210 dev_dbg(cdns->dev, "Message len %d transferred in %d frames (%d per frame)\n", 171 - msg->len, num_frames, data_per_frame); 211 + len, num_frames, data_per_frame); 172 212 dev_dbg(cdns->dev, "sizes pdi0 %d pdi1 %d tx_bandwidth %d rx_bandwidth %d\n", 173 213 pdi0_buffer_size, pdi1_buffer_size, tx_dma_bandwidth, rx_dma_bandwidth); 174 214 ··· 237 169 } 238 170 239 171 if (!command) { 240 - ret = sdw_cdns_prepare_write_dma_buffer(msg->dev_num, msg->addr, msg->buf, 241 - msg->len, data_per_frame, 172 + ret = sdw_cdns_prepare_write_dma_buffer(msg->dev_num, msg->sec, msg->sections, 173 + data_per_frame, 242 174 sdw->bpt_ctx.dmab_tx_bdl.area, 243 175 pdi0_buffer_size, &tx_total_bytes); 244 176 } else { 245 - ret = sdw_cdns_prepare_read_dma_buffer(msg->dev_num, msg->addr, msg->len, 177 + ret = sdw_cdns_prepare_read_dma_buffer(msg->dev_num, msg->sec, msg->sections, 246 178 data_per_frame, 247 179 sdw->bpt_ctx.dmab_tx_bdl.area, 248 - pdi0_buffer_size, &tx_total_bytes); 180 + pdi0_buffer_size, &tx_total_bytes, 181 + fake_size); 249 182 } 250 183 251 184 if (!ret) ··· 321 252 struct sdw_bpt_msg *msg) 322 253 { 323 254 struct sdw_cdns *cdns = &sdw->cdns; 255 + int len = 0; 324 256 int ret; 257 + int i; 325 258 326 - if (msg->len < INTEL_BPT_MSG_BYTE_MIN) { 259 + for (i = 0; i < msg->sections; i++) 260 + len += msg->sec[i].len; 261 + 262 + if (len < INTEL_BPT_MSG_BYTE_MIN) { 327 263 dev_err(cdns->dev, "BPT message length %d is less than the minimum bytes %d\n", 328 - msg->len, INTEL_BPT_MSG_BYTE_MIN); 264 + len, INTEL_BPT_MSG_BYTE_MIN); 329 265 return -EINVAL; 330 266 } 331 267 ··· 390 316 } else { 391 317 ret = sdw_cdns_check_read_response(cdns->dev, sdw->bpt_ctx.dmab_rx_bdl.area, 392 318 sdw->bpt_ctx.pdi1_buffer_size, 393 - msg->buf, msg->len, sdw->bpt_ctx.num_frames, 319 + msg->sec, msg->sections, sdw->bpt_ctx.num_frames, 394 320 sdw->bpt_ctx.data_per_frame); 395 321 if (ret < 0) 396 322 dev_err(cdns->dev, "%s: BPT Read failed %d\n", __func__, ret);
+154 -103
drivers/soundwire/qcom.c
··· 31 31 #define SWRM_VERSION_1_5_1 0x01050001 32 32 #define SWRM_VERSION_1_7_0 0x01070000 33 33 #define SWRM_VERSION_2_0_0 0x02000000 34 + #define SWRM_VERSION_3_1_0 0x03010000 34 35 #define SWRM_COMP_HW_VERSION 0x00 35 36 #define SWRM_COMP_CFG_ADDR 0x04 36 37 #define SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK BIT(1) ··· 41 40 #define SWRM_COMP_PARAMS_RD_FIFO_DEPTH GENMASK(19, 15) 42 41 #define SWRM_COMP_PARAMS_DOUT_PORTS_MASK GENMASK(4, 0) 43 42 #define SWRM_COMP_PARAMS_DIN_PORTS_MASK GENMASK(9, 5) 43 + #define SWRM_V3_COMP_PARAMS_WR_FIFO_DEPTH GENMASK(17, 10) 44 + #define SWRM_V3_COMP_PARAMS_RD_FIFO_DEPTH GENMASK(23, 18) 45 + 44 46 #define SWRM_COMP_MASTER_ID 0x104 45 47 #define SWRM_V1_3_INTERRUPT_STATUS 0x200 46 48 #define SWRM_V2_0_INTERRUPT_STATUS 0x5000 ··· 103 99 #define SWRM_MCP_SLV_STATUS 0x1090 104 100 #define SWRM_MCP_SLV_STATUS_MASK GENMASK(1, 0) 105 101 #define SWRM_MCP_SLV_STATUS_SZ 2 106 - #define SWRM_DP_PORT_CTRL_BANK(n, m) (0x1124 + 0x100 * (n - 1) + 0x40 * m) 107 - #define SWRM_DP_PORT_CTRL_2_BANK(n, m) (0x1128 + 0x100 * (n - 1) + 0x40 * m) 108 - #define SWRM_DP_BLOCK_CTRL_1(n) (0x112C + 0x100 * (n - 1)) 109 - #define SWRM_DP_BLOCK_CTRL2_BANK(n, m) (0x1130 + 0x100 * (n - 1) + 0x40 * m) 110 - #define SWRM_DP_PORT_HCTRL_BANK(n, m) (0x1134 + 0x100 * (n - 1) + 0x40 * m) 111 - #define SWRM_DP_BLOCK_CTRL3_BANK(n, m) (0x1138 + 0x100 * (n - 1) + 0x40 * m) 112 - #define SWRM_DP_SAMPLECTRL2_BANK(n, m) (0x113C + 0x100 * (n - 1) + 0x40 * m) 113 - #define SWRM_DIN_DPn_PCM_PORT_CTRL(n) (0x1054 + 0x100 * (n - 1)) 102 + 103 + #define SWRM_DPn_PORT_CTRL_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m) 104 + #define SWRM_DPn_PORT_CTRL_2_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m) 105 + #define SWRM_DPn_BLOCK_CTRL_1(offset, n) (offset + 0x100 * (n - 1)) 106 + #define SWRM_DPn_BLOCK_CTRL2_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m) 107 + #define SWRM_DPn_PORT_HCTRL_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m) 108 + #define SWRM_DPn_BLOCK_CTRL3_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m) 109 + #define SWRM_DPn_SAMPLECTRL2_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m) 110 + 114 111 #define SWR_V1_3_MSTR_MAX_REG_ADDR 0x1740 115 112 #define SWR_V2_0_MSTR_MAX_REG_ADDR 0x50ac 116 113 ··· 133 128 #define MAX_FREQ_NUM 1 134 129 #define TIMEOUT_MS 100 135 130 #define QCOM_SWRM_MAX_RD_LEN 0x1 136 - #define QCOM_SDW_MAX_PORTS 14 137 131 #define DEFAULT_CLK_FREQ 9600000 138 132 #define SWRM_MAX_DAIS 0xF 139 133 #define SWR_INVALID_PARAM 0xFF ··· 176 172 SWRM_REG_CMD_FIFO_RD_CMD, 177 173 SWRM_REG_CMD_FIFO_STATUS, 178 174 SWRM_REG_CMD_FIFO_RD_FIFO_ADDR, 175 + SWRM_OFFSET_DP_PORT_CTRL_BANK, 176 + SWRM_OFFSET_DP_PORT_CTRL_2_BANK, 177 + SWRM_OFFSET_DP_BLOCK_CTRL_1, 178 + SWRM_OFFSET_DP_BLOCK_CTRL2_BANK, 179 + SWRM_OFFSET_DP_PORT_HCTRL_BANK, 180 + SWRM_OFFSET_DP_BLOCK_CTRL3_BANK, 181 + SWRM_OFFSET_DP_SAMPLECTRL2_BANK, 179 182 }; 180 183 181 184 struct qcom_swrm_ctrl { ··· 206 195 int wake_irq; 207 196 int num_din_ports; 208 197 int num_dout_ports; 198 + int nports; 209 199 int cols_index; 210 200 int rows_index; 211 201 unsigned long port_mask; ··· 214 202 u8 rcmd_id; 215 203 u8 wcmd_id; 216 204 /* Port numbers are 1 - 14 */ 217 - struct qcom_swrm_port_config pconfig[QCOM_SDW_MAX_PORTS + 1]; 205 + struct qcom_swrm_port_config *pconfig; 218 206 struct sdw_stream_runtime *sruntime[SWRM_MAX_DAIS]; 219 207 enum sdw_slave_status status[SDW_MAX_DEVICES + 1]; 220 208 int (*reg_read)(struct qcom_swrm_ctrl *ctrl, int reg, u32 *val); 221 209 int (*reg_write)(struct qcom_swrm_ctrl *ctrl, int reg, int val); 222 210 u32 slave_status; 223 211 u32 wr_fifo_depth; 224 - u32 rd_fifo_depth; 225 212 bool clock_stop_not_supported; 226 213 }; 227 214 ··· 242 231 [SWRM_REG_CMD_FIFO_RD_CMD] = SWRM_V1_3_CMD_FIFO_RD_CMD, 243 232 [SWRM_REG_CMD_FIFO_STATUS] = SWRM_V1_3_CMD_FIFO_STATUS, 244 233 [SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] = SWRM_V1_3_CMD_FIFO_RD_FIFO_ADDR, 234 + [SWRM_OFFSET_DP_PORT_CTRL_BANK] = 0x1124, 235 + [SWRM_OFFSET_DP_PORT_CTRL_2_BANK] = 0x1128, 236 + [SWRM_OFFSET_DP_BLOCK_CTRL_1] = 0x112c, 237 + [SWRM_OFFSET_DP_BLOCK_CTRL2_BANK] = 0x1130, 238 + [SWRM_OFFSET_DP_PORT_HCTRL_BANK] = 0x1134, 239 + [SWRM_OFFSET_DP_BLOCK_CTRL3_BANK] = 0x1138, 240 + [SWRM_OFFSET_DP_SAMPLECTRL2_BANK] = 0x113c, 245 241 }; 246 242 247 243 static const struct qcom_swrm_data swrm_v1_3_data = { ··· 283 265 [SWRM_REG_CMD_FIFO_RD_CMD] = SWRM_V2_0_CMD_FIFO_RD_CMD, 284 266 [SWRM_REG_CMD_FIFO_STATUS] = SWRM_V2_0_CMD_FIFO_STATUS, 285 267 [SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] = SWRM_V2_0_CMD_FIFO_RD_FIFO_ADDR, 268 + [SWRM_OFFSET_DP_PORT_CTRL_BANK] = 0x1124, 269 + [SWRM_OFFSET_DP_PORT_CTRL_2_BANK] = 0x1128, 270 + [SWRM_OFFSET_DP_BLOCK_CTRL_1] = 0x112c, 271 + [SWRM_OFFSET_DP_BLOCK_CTRL2_BANK] = 0x1130, 272 + [SWRM_OFFSET_DP_PORT_HCTRL_BANK] = 0x1134, 273 + [SWRM_OFFSET_DP_BLOCK_CTRL3_BANK] = 0x1138, 274 + [SWRM_OFFSET_DP_SAMPLECTRL2_BANK] = 0x113c, 286 275 }; 287 276 288 277 static const struct qcom_swrm_data swrm_v2_0_data = { ··· 300 275 .reg_layout = swrm_v2_0_reg_layout, 301 276 }; 302 277 278 + static const unsigned int swrm_v3_0_reg_layout[] = { 279 + [SWRM_REG_FRAME_GEN_ENABLED] = SWRM_V2_0_LINK_STATUS, 280 + [SWRM_REG_INTERRUPT_STATUS] = SWRM_V2_0_INTERRUPT_STATUS, 281 + [SWRM_REG_INTERRUPT_MASK_ADDR] = 0, /* Not present */ 282 + [SWRM_REG_INTERRUPT_CLEAR] = SWRM_V2_0_INTERRUPT_CLEAR, 283 + [SWRM_REG_INTERRUPT_CPU_EN] = SWRM_V2_0_INTERRUPT_CPU_EN, 284 + [SWRM_REG_CMD_FIFO_WR_CMD] = SWRM_V2_0_CMD_FIFO_WR_CMD, 285 + [SWRM_REG_CMD_FIFO_RD_CMD] = SWRM_V2_0_CMD_FIFO_RD_CMD, 286 + [SWRM_REG_CMD_FIFO_STATUS] = SWRM_V2_0_CMD_FIFO_STATUS, 287 + [SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] = SWRM_V2_0_CMD_FIFO_RD_FIFO_ADDR, 288 + [SWRM_OFFSET_DP_PORT_CTRL_BANK] = 0x1224, 289 + [SWRM_OFFSET_DP_PORT_CTRL_2_BANK] = 0x1228, 290 + [SWRM_OFFSET_DP_BLOCK_CTRL_1] = 0x122c, 291 + [SWRM_OFFSET_DP_BLOCK_CTRL2_BANK] = 0x1230, 292 + [SWRM_OFFSET_DP_PORT_HCTRL_BANK] = 0x1234, 293 + [SWRM_OFFSET_DP_BLOCK_CTRL3_BANK] = 0x1238, 294 + [SWRM_OFFSET_DP_SAMPLECTRL2_BANK] = 0x123c, 295 + }; 296 + 297 + static const struct qcom_swrm_data swrm_v3_0_data = { 298 + .default_rows = 50, 299 + .default_cols = 16, 300 + .sw_clk_gate_required = true, 301 + .max_reg = SWR_V2_0_MSTR_MAX_REG_ADDR, 302 + .reg_layout = swrm_v3_0_reg_layout, 303 + }; 303 304 #define to_qcom_sdw(b) container_of(b, struct qcom_swrm_ctrl, bus) 304 305 305 306 static int qcom_swrm_ahb_reg_read(struct qcom_swrm_ctrl *ctrl, int reg, ··· 949 898 swrm_wait_for_frame_gen_enabled(ctrl); 950 899 ctrl->slave_status = 0; 951 900 ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val); 952 - ctrl->rd_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_RD_FIFO_DEPTH, val); 953 - ctrl->wr_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_WR_FIFO_DEPTH, val); 901 + 902 + if (ctrl->version >= SWRM_VERSION_3_1_0) 903 + ctrl->wr_fifo_depth = FIELD_GET(SWRM_V3_COMP_PARAMS_WR_FIFO_DEPTH, val); 904 + else 905 + ctrl->wr_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_WR_FIFO_DEPTH, val); 954 906 955 907 return 0; 956 908 } ··· 1020 966 unsigned int bank) 1021 967 { 1022 968 struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); 969 + u32 offset = ctrl->reg_layout[SWRM_OFFSET_DP_BLOCK_CTRL_1]; 1023 970 1024 - return ctrl->reg_write(ctrl, SWRM_DP_BLOCK_CTRL_1(p_params->num), 1025 - p_params->bps - 1); 1026 - 971 + return ctrl->reg_write(ctrl, SWRM_DPn_BLOCK_CTRL_1(offset, p_params->num), 972 + p_params->bps - 1); 1027 973 } 1028 974 1029 975 static int qcom_swrm_transport_params(struct sdw_bus *bus, ··· 1033 979 struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); 1034 980 struct qcom_swrm_port_config *pcfg; 1035 981 u32 value; 1036 - int reg = SWRM_DP_PORT_CTRL_BANK((params->port_num), bank); 982 + int reg, offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_CTRL_BANK]; 1037 983 int ret; 984 + 985 + reg = SWRM_DPn_PORT_CTRL_BANK(offset, params->port_num, bank); 1038 986 1039 987 pcfg = &ctrl->pconfig[params->port_num]; 1040 988 ··· 1049 993 goto err; 1050 994 1051 995 if (pcfg->si > 0xff) { 996 + offset = ctrl->reg_layout[SWRM_OFFSET_DP_SAMPLECTRL2_BANK]; 1052 997 value = (pcfg->si >> 8) & 0xff; 1053 - reg = SWRM_DP_SAMPLECTRL2_BANK(params->port_num, bank); 998 + reg = SWRM_DPn_SAMPLECTRL2_BANK(offset, params->port_num, bank); 999 + 1054 1000 ret = ctrl->reg_write(ctrl, reg, value); 1055 1001 if (ret) 1056 1002 goto err; 1057 1003 } 1058 1004 1059 1005 if (pcfg->lane_control != SWR_INVALID_PARAM) { 1060 - reg = SWRM_DP_PORT_CTRL_2_BANK(params->port_num, bank); 1006 + offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_CTRL_2_BANK]; 1007 + reg = SWRM_DPn_PORT_CTRL_2_BANK(offset, params->port_num, bank); 1008 + 1061 1009 value = pcfg->lane_control; 1062 1010 ret = ctrl->reg_write(ctrl, reg, value); 1063 1011 if (ret) ··· 1069 1009 } 1070 1010 1071 1011 if (pcfg->blk_group_count != SWR_INVALID_PARAM) { 1072 - reg = SWRM_DP_BLOCK_CTRL2_BANK(params->port_num, bank); 1012 + offset = ctrl->reg_layout[SWRM_OFFSET_DP_BLOCK_CTRL2_BANK]; 1013 + 1014 + reg = SWRM_DPn_BLOCK_CTRL2_BANK(offset, params->port_num, bank); 1015 + 1073 1016 value = pcfg->blk_group_count; 1074 1017 ret = ctrl->reg_write(ctrl, reg, value); 1075 1018 if (ret) 1076 1019 goto err; 1077 1020 } 1078 1021 1079 - if (pcfg->hstart != SWR_INVALID_PARAM 1080 - && pcfg->hstop != SWR_INVALID_PARAM) { 1081 - reg = SWRM_DP_PORT_HCTRL_BANK(params->port_num, bank); 1022 + offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_HCTRL_BANK]; 1023 + reg = SWRM_DPn_PORT_HCTRL_BANK(offset, params->port_num, bank); 1024 + 1025 + if (pcfg->hstart != SWR_INVALID_PARAM && pcfg->hstop != SWR_INVALID_PARAM) { 1082 1026 value = (pcfg->hstop << 4) | pcfg->hstart; 1083 1027 ret = ctrl->reg_write(ctrl, reg, value); 1084 1028 } else { 1085 - reg = SWRM_DP_PORT_HCTRL_BANK(params->port_num, bank); 1086 1029 value = (SWR_HSTOP_MAX_VAL << 4) | SWR_HSTART_MIN_VAL; 1087 1030 ret = ctrl->reg_write(ctrl, reg, value); 1088 1031 } ··· 1094 1031 goto err; 1095 1032 1096 1033 if (pcfg->bp_mode != SWR_INVALID_PARAM) { 1097 - reg = SWRM_DP_BLOCK_CTRL3_BANK(params->port_num, bank); 1034 + offset = ctrl->reg_layout[SWRM_OFFSET_DP_BLOCK_CTRL3_BANK]; 1035 + reg = SWRM_DPn_BLOCK_CTRL3_BANK(offset, params->port_num, bank); 1098 1036 ret = ctrl->reg_write(ctrl, reg, pcfg->bp_mode); 1099 1037 } 1100 1038 ··· 1107 1043 struct sdw_enable_ch *enable_ch, 1108 1044 unsigned int bank) 1109 1045 { 1110 - u32 reg = SWRM_DP_PORT_CTRL_BANK(enable_ch->port_num, bank); 1046 + u32 reg; 1111 1047 struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus); 1112 1048 u32 val; 1049 + u32 offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_CTRL_BANK]; 1050 + 1051 + reg = SWRM_DPn_PORT_CTRL_BANK(offset, enable_ch->port_num, bank); 1113 1052 1114 1053 ctrl->reg_read(ctrl, reg, &val); 1115 1054 ··· 1222 1155 struct snd_pcm_hw_params *params, 1223 1156 int direction) 1224 1157 { 1225 - struct sdw_port_config pconfig[QCOM_SDW_MAX_PORTS]; 1226 1158 struct sdw_stream_config sconfig; 1227 1159 struct sdw_master_runtime *m_rt; 1228 1160 struct sdw_slave_runtime *s_rt; ··· 1230 1164 unsigned long *port_mask; 1231 1165 int maxport, pn, nports = 0, ret = 0; 1232 1166 unsigned int m_port; 1167 + struct sdw_port_config *pconfig __free(kfree) = kcalloc(ctrl->nports, 1168 + sizeof(*pconfig), GFP_KERNEL); 1169 + if (!pconfig) 1170 + return -ENOMEM; 1233 1171 1234 1172 if (direction == SNDRV_PCM_STREAM_CAPTURE) 1235 1173 sconfig.direction = SDW_DATA_DIR_TX; ··· 1258 1188 continue; 1259 1189 1260 1190 port_mask = &ctrl->port_mask; 1261 - maxport = ctrl->num_dout_ports + ctrl->num_din_ports; 1262 - 1191 + maxport = ctrl->nports; 1263 1192 1264 1193 list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) { 1265 1194 slave = s_rt->slave; ··· 1418 1349 static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl) 1419 1350 { 1420 1351 struct device_node *np = ctrl->dev->of_node; 1421 - u8 off1[QCOM_SDW_MAX_PORTS]; 1422 - u8 off2[QCOM_SDW_MAX_PORTS]; 1423 - u16 si[QCOM_SDW_MAX_PORTS]; 1424 - u8 bp_mode[QCOM_SDW_MAX_PORTS] = { 0, }; 1425 - u8 hstart[QCOM_SDW_MAX_PORTS]; 1426 - u8 hstop[QCOM_SDW_MAX_PORTS]; 1427 - u8 word_length[QCOM_SDW_MAX_PORTS]; 1428 - u8 blk_group_count[QCOM_SDW_MAX_PORTS]; 1429 - u8 lane_control[QCOM_SDW_MAX_PORTS]; 1430 - int i, ret, nports, val; 1431 - bool si_16 = false; 1352 + struct qcom_swrm_port_config *pcfg; 1353 + int i, ret, val; 1432 1354 1433 1355 ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val); 1434 1356 ··· 1427 1367 ctrl->num_din_ports = FIELD_GET(SWRM_COMP_PARAMS_DIN_PORTS_MASK, val); 1428 1368 1429 1369 ret = of_property_read_u32(np, "qcom,din-ports", &val); 1430 - if (ret) 1431 - return ret; 1370 + if (!ret) { /* only if present */ 1371 + if (val != ctrl->num_din_ports) { 1372 + dev_err(ctrl->dev, "din-ports (%d) mismatch with controller (%d)", 1373 + val, ctrl->num_din_ports); 1374 + } 1432 1375 1433 - if (val > ctrl->num_din_ports) 1434 - return -EINVAL; 1435 - 1436 - ctrl->num_din_ports = val; 1376 + ctrl->num_din_ports = val; 1377 + } 1437 1378 1438 1379 ret = of_property_read_u32(np, "qcom,dout-ports", &val); 1439 - if (ret) 1440 - return ret; 1380 + if (!ret) { /* only if present */ 1381 + if (val != ctrl->num_dout_ports) { 1382 + dev_err(ctrl->dev, "dout-ports (%d) mismatch with controller (%d)", 1383 + val, ctrl->num_dout_ports); 1384 + } 1441 1385 1442 - if (val > ctrl->num_dout_ports) 1443 - return -EINVAL; 1386 + ctrl->num_dout_ports = val; 1387 + } 1444 1388 1445 - ctrl->num_dout_ports = val; 1389 + ctrl->nports = ctrl->num_dout_ports + ctrl->num_din_ports; 1446 1390 1447 - nports = ctrl->num_dout_ports + ctrl->num_din_ports; 1448 - if (nports > QCOM_SDW_MAX_PORTS) 1449 - return -EINVAL; 1391 + ctrl->pconfig = devm_kcalloc(ctrl->dev, ctrl->nports + 1, 1392 + sizeof(*ctrl->pconfig), GFP_KERNEL); 1393 + if (!ctrl->pconfig) 1394 + return -ENOMEM; 1450 1395 1451 - /* Valid port numbers are from 1-14, so mask out port 0 explicitly */ 1452 1396 set_bit(0, &ctrl->port_mask); 1397 + /* Valid port numbers are from 1, so mask out port 0 explicitly */ 1398 + for (i = 0; i < ctrl->nports; i++) { 1399 + pcfg = &ctrl->pconfig[i + 1]; 1453 1400 1454 - ret = of_property_read_u8_array(np, "qcom,ports-offset1", 1455 - off1, nports); 1456 - if (ret) 1457 - return ret; 1458 - 1459 - ret = of_property_read_u8_array(np, "qcom,ports-offset2", 1460 - off2, nports); 1461 - if (ret) 1462 - return ret; 1463 - 1464 - ret = of_property_read_u8_array(np, "qcom,ports-sinterval-low", 1465 - (u8 *)si, nports); 1466 - if (ret) { 1467 - ret = of_property_read_u16_array(np, "qcom,ports-sinterval", 1468 - si, nports); 1401 + ret = of_property_read_u8_index(np, "qcom,ports-offset1", i, &pcfg->off1); 1469 1402 if (ret) 1470 1403 return ret; 1471 - si_16 = true; 1472 - } 1473 1404 1474 - ret = of_property_read_u8_array(np, "qcom,ports-block-pack-mode", 1475 - bp_mode, nports); 1476 - if (ret) { 1477 - if (ctrl->version <= SWRM_VERSION_1_3_0) 1478 - memset(bp_mode, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); 1479 - else 1405 + ret = of_property_read_u8_index(np, "qcom,ports-offset2", i, &pcfg->off2); 1406 + if (ret) 1480 1407 return ret; 1481 - } 1482 1408 1483 - memset(hstart, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); 1484 - of_property_read_u8_array(np, "qcom,ports-hstart", hstart, nports); 1409 + ret = of_property_read_u8_index(np, "qcom,ports-sinterval-low", i, (u8 *)&pcfg->si); 1410 + if (ret) { 1411 + ret = of_property_read_u16_index(np, "qcom,ports-sinterval", i, &pcfg->si); 1412 + if (ret) 1413 + return ret; 1414 + } 1485 1415 1486 - memset(hstop, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); 1487 - of_property_read_u8_array(np, "qcom,ports-hstop", hstop, nports); 1416 + ret = of_property_read_u8_index(np, "qcom,ports-block-pack-mode", 1417 + i, &pcfg->bp_mode); 1418 + if (ret) { 1419 + if (ctrl->version <= SWRM_VERSION_1_3_0) 1420 + pcfg->bp_mode = SWR_INVALID_PARAM; 1421 + else 1422 + return ret; 1423 + } 1488 1424 1489 - memset(word_length, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); 1490 - of_property_read_u8_array(np, "qcom,ports-word-length", word_length, nports); 1425 + /* Optional properties */ 1426 + pcfg->hstart = SWR_INVALID_PARAM; 1427 + pcfg->hstop = SWR_INVALID_PARAM; 1428 + pcfg->word_length = SWR_INVALID_PARAM; 1429 + pcfg->blk_group_count = SWR_INVALID_PARAM; 1430 + pcfg->lane_control = SWR_INVALID_PARAM; 1491 1431 1492 - memset(blk_group_count, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); 1493 - of_property_read_u8_array(np, "qcom,ports-block-group-count", blk_group_count, nports); 1432 + of_property_read_u8_index(np, "qcom,ports-hstart", i, &pcfg->hstart); 1494 1433 1495 - memset(lane_control, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS); 1496 - of_property_read_u8_array(np, "qcom,ports-lane-control", lane_control, nports); 1434 + of_property_read_u8_index(np, "qcom,ports-hstop", i, &pcfg->hstop); 1497 1435 1498 - for (i = 0; i < nports; i++) { 1499 - /* Valid port number range is from 1-14 */ 1500 - if (si_16) 1501 - ctrl->pconfig[i + 1].si = si[i]; 1502 - else 1503 - ctrl->pconfig[i + 1].si = ((u8 *)si)[i]; 1504 - ctrl->pconfig[i + 1].off1 = off1[i]; 1505 - ctrl->pconfig[i + 1].off2 = off2[i]; 1506 - ctrl->pconfig[i + 1].bp_mode = bp_mode[i]; 1507 - ctrl->pconfig[i + 1].hstart = hstart[i]; 1508 - ctrl->pconfig[i + 1].hstop = hstop[i]; 1509 - ctrl->pconfig[i + 1].word_length = word_length[i]; 1510 - ctrl->pconfig[i + 1].blk_group_count = blk_group_count[i]; 1511 - ctrl->pconfig[i + 1].lane_control = lane_control[i]; 1436 + of_property_read_u8_index(np, "qcom,ports-word-length", i, &pcfg->word_length); 1437 + 1438 + of_property_read_u8_index(np, "qcom,ports-block-group-count", 1439 + i, &pcfg->blk_group_count); 1440 + 1441 + of_property_read_u8_index(np, "qcom,ports-lane-control", i, &pcfg->lane_control); 1512 1442 } 1513 1443 1514 1444 return 0; ··· 1819 1769 { .compatible = "qcom,soundwire-v1.6.0", .data = &swrm_v1_6_data }, 1820 1770 { .compatible = "qcom,soundwire-v1.7.0", .data = &swrm_v1_5_data }, 1821 1771 { .compatible = "qcom,soundwire-v2.0.0", .data = &swrm_v2_0_data }, 1772 + { .compatible = "qcom,soundwire-v3.1.0", .data = &swrm_v3_0_data }, 1822 1773 {/* sentinel */}, 1823 1774 }; 1824 1775
+9
include/linux/of.h
··· 316 316 extern bool of_property_read_bool(const struct device_node *np, const char *propname); 317 317 extern int of_property_count_elems_of_size(const struct device_node *np, 318 318 const char *propname, int elem_size); 319 + extern int of_property_read_u8_index(const struct device_node *np, 320 + const char *propname, 321 + u32 index, u8 *out_value); 319 322 extern int of_property_read_u16_index(const struct device_node *np, 320 323 const char *propname, 321 324 u32 index, u16 *out_value); ··· 647 644 648 645 static inline int of_property_count_elems_of_size(const struct device_node *np, 649 646 const char *propname, int elem_size) 647 + { 648 + return -ENOSYS; 649 + } 650 + 651 + static inline int of_property_read_u8_index(const struct device_node *np, 652 + const char *propname, u32 index, u8 *out_value) 650 653 { 651 654 return -ENOSYS; 652 655 }
+7
include/sound/hda-sdw-bpt.h
··· 30 30 int hda_sdw_bpt_close(struct device *dev, struct hdac_ext_stream *bpt_tx_stream, 31 31 struct snd_dma_buffer *dmab_tx_bdl, struct hdac_ext_stream *bpt_rx_stream, 32 32 struct snd_dma_buffer *dmab_rx_bdl); 33 + 34 + unsigned int hda_sdw_bpt_get_buf_size_alignment(unsigned int dma_bandwidth); 33 35 #else 34 36 static inline int hda_sdw_bpt_open(struct device *dev, int link_id, 35 37 struct hdac_ext_stream **bpt_tx_stream, ··· 65 63 { 66 64 WARN_ONCE(1, "SoundWire BPT is disabled"); 67 65 return -EOPNOTSUPP; 66 + } 67 + 68 + static inline unsigned int hda_sdw_bpt_get_buf_size_alignment(unsigned int dma_bandwidth) 69 + { 70 + return 0; 68 71 } 69 72 #endif 70 73
+13
sound/soc/sof/intel/hda-sdw-bpt.c
··· 10 10 * Hardware interface for SoundWire BPT support with HDA DMA 11 11 */ 12 12 13 + #include <linux/lcm.h> 13 14 #include <sound/hdaudio_ext.h> 14 15 #include <sound/hda-mlink.h> 15 16 #include <sound/hda-sdw-bpt.h> ··· 236 235 237 236 return ret; 238 237 } 238 + 239 + #define FIFO_ALIGNMENT 64 240 + 241 + unsigned int hda_sdw_bpt_get_buf_size_alignment(unsigned int dma_bandwidth) 242 + { 243 + unsigned int num_channels = DIV_ROUND_UP(dma_bandwidth, BPT_FREQUENCY * 32); 244 + unsigned int data_block = num_channels * 4; 245 + unsigned int alignment = lcm(data_block, FIFO_ALIGNMENT); 246 + 247 + return alignment; 248 + } 249 + EXPORT_SYMBOL_NS(hda_sdw_bpt_get_buf_size_alignment, "SND_SOC_SOF_INTEL_HDA_SDW_BPT"); 239 250 240 251 int hda_sdw_bpt_open(struct device *dev, int link_id, struct hdac_ext_stream **bpt_tx_stream, 241 252 struct snd_dma_buffer *dmab_tx_bdl, u32 bpt_tx_num_bytes,