Bug Summary

File:dev/pci/drm/amd/display/dc/dce/dce_aux.c
Warning:line 586, column 3
Value stored to 'bytes_replied' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name dce_aux.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/pci/drm/amd/display/dc/dce/dce_aux.c
1/*
2 * Copyright 2012-15 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25
26#include <linux/delay.h>
27#include <linux/slab.h>
28
29#include "dm_services.h"
30#include "core_types.h"
31#include "dce_aux.h"
32#include "dce/dce_11_0_sh_mask.h"
33#include "dm_event_log.h"
34
35#define CTXaux110->base.ctx \
36 aux110->base.ctx
37#define REG(reg_name)(aux110->regs->reg_name)\
38 (aux110->regs->reg_name)
39
40#define DC_LOGGERengine->ctx->logger \
41 engine->ctx->logger
42
43#include "reg_helper.h"
44
45#undef FN
46#define FN(reg_name, field_name)aux110->shift->field_name, aux110->mask->field_name \
47 aux110->shift->field_name, aux110->mask->field_name
48
49#define FROM_AUX_ENGINE(ptr)({ const __typeof( ((struct aux_engine_dce110 *)0)->base )
*__mptr = ((ptr)); (struct aux_engine_dce110 *)( (char *)__mptr
- __builtin_offsetof(struct aux_engine_dce110, base) );})
\
50 container_of((ptr), struct aux_engine_dce110, base)({ const __typeof( ((struct aux_engine_dce110 *)0)->base )
*__mptr = ((ptr)); (struct aux_engine_dce110 *)( (char *)__mptr
- __builtin_offsetof(struct aux_engine_dce110, base) );})
51
52#define FROM_ENGINE(ptr)({ const __typeof( ((struct aux_engine_dce110 *)0)->base )
*__mptr = ((({ const __typeof( ((struct dce_aux *)0)->base
) *__mptr = ((ptr)); (struct dce_aux *)( (char *)__mptr - __builtin_offsetof
(struct dce_aux, base) );}))); (struct aux_engine_dce110 *)( (
char *)__mptr - __builtin_offsetof(struct aux_engine_dce110, base
) );})
\
53 FROM_AUX_ENGINE(container_of((ptr), struct dce_aux, base))({ const __typeof( ((struct aux_engine_dce110 *)0)->base )
*__mptr = ((({ const __typeof( ((struct dce_aux *)0)->base
) *__mptr = ((ptr)); (struct dce_aux *)( (char *)__mptr - __builtin_offsetof
(struct dce_aux, base) );}))); (struct aux_engine_dce110 *)( (
char *)__mptr - __builtin_offsetof(struct aux_engine_dce110, base
) );})
54
55#define FROM_AUX_ENGINE_ENGINE(ptr)({ const __typeof( ((struct dce_aux *)0)->base ) *__mptr =
((ptr)); (struct dce_aux *)( (char *)__mptr - __builtin_offsetof
(struct dce_aux, base) );})
\
56 container_of((ptr), struct dce_aux, base)({ const __typeof( ((struct dce_aux *)0)->base ) *__mptr =
((ptr)); (struct dce_aux *)( (char *)__mptr - __builtin_offsetof
(struct dce_aux, base) );})
57enum {
58 AUX_INVALID_REPLY_RETRY_COUNTER = 1,
59 AUX_TIMED_OUT_RETRY_COUNTER = 2,
60 AUX_DEFER_RETRY_COUNTER = 6
61};
62
63#define TIME_OUT_INCREMENT1016 1016
64#define TIME_OUT_MULTIPLIER_88 8
65#define TIME_OUT_MULTIPLIER_1616 16
66#define TIME_OUT_MULTIPLIER_3232 32
67#define TIME_OUT_MULTIPLIER_6464 64
68#define MAX_TIMEOUT_LENGTH127 127
69#define DEFAULT_AUX_ENGINE_MULT0 0
70#define DEFAULT_AUX_ENGINE_LENGTH69 69
71
72static void release_engine(
73 struct dce_aux *engine)
74{
75 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine)({ const __typeof( ((struct aux_engine_dce110 *)0)->base )
*__mptr = ((engine)); (struct aux_engine_dce110 *)( (char *)
__mptr - __builtin_offsetof(struct aux_engine_dce110, base) )
;})
;
76
77 dal_ddc_close(engine->ddc);
78
79 engine->ddc = NULL((void *)0);
80
81 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1)generic_reg_update_ex(aux110->base.ctx, (aux110->regs->
AUX_ARB_CONTROL), 1, aux110->shift->AUX_SW_DONE_USING_AUX_REG
, aux110->mask->AUX_SW_DONE_USING_AUX_REG, 1)
;
82}
83
84#define SW_CAN_ACCESS_AUX1 1
85#define DMCU_CAN_ACCESS_AUX2 2
86
87static bool_Bool is_engine_available(
88 struct dce_aux *engine)
89{
90 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine)({ const __typeof( ((struct aux_engine_dce110 *)0)->base )
*__mptr = ((engine)); (struct aux_engine_dce110 *)( (char *)
__mptr - __builtin_offsetof(struct aux_engine_dce110, base) )
;})
;
91
92 uint32_t value = REG_READ(AUX_ARB_CONTROL)dm_read_reg_func(aux110->base.ctx, (aux110->regs->AUX_ARB_CONTROL
), __func__)
;
93 uint32_t field = get_reg_field_value(get_reg_field_value_ex( (value), 0xc, 0x2)
94 value,get_reg_field_value_ex( (value), 0xc, 0x2)
95 AUX_ARB_CONTROL,get_reg_field_value_ex( (value), 0xc, 0x2)
96 AUX_REG_RW_CNTL_STATUS)get_reg_field_value_ex( (value), 0xc, 0x2);
97
98 return (field != DMCU_CAN_ACCESS_AUX2);
99}
100static bool_Bool acquire_engine(
101 struct dce_aux *engine)
102{
103 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine)({ const __typeof( ((struct aux_engine_dce110 *)0)->base )
*__mptr = ((engine)); (struct aux_engine_dce110 *)( (char *)
__mptr - __builtin_offsetof(struct aux_engine_dce110, base) )
;})
;
104
105 uint32_t value = REG_READ(AUX_ARB_CONTROL)dm_read_reg_func(aux110->base.ctx, (aux110->regs->AUX_ARB_CONTROL
), __func__)
;
106 uint32_t field = get_reg_field_value(get_reg_field_value_ex( (value), 0xc, 0x2)
107 value,get_reg_field_value_ex( (value), 0xc, 0x2)
108 AUX_ARB_CONTROL,get_reg_field_value_ex( (value), 0xc, 0x2)
109 AUX_REG_RW_CNTL_STATUS)get_reg_field_value_ex( (value), 0xc, 0x2);
110 if (field == DMCU_CAN_ACCESS_AUX2)
111 return false0;
112 /* enable AUX before request SW to access AUX */
113 value = REG_READ(AUX_CONTROL)dm_read_reg_func(aux110->base.ctx, (aux110->regs->AUX_CONTROL
), __func__)
;
114 field = get_reg_field_value(value,get_reg_field_value_ex( (value), 0x1, 0x0)
115 AUX_CONTROL,get_reg_field_value_ex( (value), 0x1, 0x0)
116 AUX_EN)get_reg_field_value_ex( (value), 0x1, 0x0);
117
118 if (field == 0) {
119 set_reg_field_value((value) = set_reg_field_value_ex( (value), (1), 0x1, 0x0)
120 value,(value) = set_reg_field_value_ex( (value), (1), 0x1, 0x0)
121 1,(value) = set_reg_field_value_ex( (value), (1), 0x1, 0x0)
122 AUX_CONTROL,(value) = set_reg_field_value_ex( (value), (1), 0x1, 0x0)
123 AUX_EN)(value) = set_reg_field_value_ex( (value), (1), 0x1, 0x0);
124
125 if (REG(AUX_RESET_MASK)(aux110->regs->AUX_RESET_MASK)) {
126 /*DP_AUX block as part of the enable sequence*/
127 set_reg_field_value((value) = set_reg_field_value_ex( (value), (1), 0x10, 0x4)
128 value,(value) = set_reg_field_value_ex( (value), (1), 0x10, 0x4)
129 1,(value) = set_reg_field_value_ex( (value), (1), 0x10, 0x4)
130 AUX_CONTROL,(value) = set_reg_field_value_ex( (value), (1), 0x10, 0x4)
131 AUX_RESET)(value) = set_reg_field_value_ex( (value), (1), 0x10, 0x4);
132 }
133
134 REG_WRITE(AUX_CONTROL, value)dm_write_reg_func(aux110->base.ctx, (aux110->regs->AUX_CONTROL
), value, __func__)
;
135
136 if (REG(AUX_RESET_MASK)(aux110->regs->AUX_RESET_MASK)) {
137 /*poll HW to make sure reset it done*/
138
139 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1,generic_reg_wait(aux110->base.ctx, (aux110->regs->AUX_CONTROL
), aux110->shift->AUX_RESET_DONE, aux110->mask->AUX_RESET_DONE
, 1, 1, 11, __func__, 140)
140 1, 11)generic_reg_wait(aux110->base.ctx, (aux110->regs->AUX_CONTROL
), aux110->shift->AUX_RESET_DONE, aux110->mask->AUX_RESET_DONE
, 1, 1, 11, __func__, 140)
;
141
142 set_reg_field_value((value) = set_reg_field_value_ex( (value), (0), 0x10, 0x4)
143 value,(value) = set_reg_field_value_ex( (value), (0), 0x10, 0x4)
144 0,(value) = set_reg_field_value_ex( (value), (0), 0x10, 0x4)
145 AUX_CONTROL,(value) = set_reg_field_value_ex( (value), (0), 0x10, 0x4)
146 AUX_RESET)(value) = set_reg_field_value_ex( (value), (0), 0x10, 0x4);
147
148 REG_WRITE(AUX_CONTROL, value)dm_write_reg_func(aux110->base.ctx, (aux110->regs->AUX_CONTROL
), value, __func__)
;
149
150 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0,generic_reg_wait(aux110->base.ctx, (aux110->regs->AUX_CONTROL
), aux110->shift->AUX_RESET_DONE, aux110->mask->AUX_RESET_DONE
, 0, 1, 11, __func__, 151)
151 1, 11)generic_reg_wait(aux110->base.ctx, (aux110->regs->AUX_CONTROL
), aux110->shift->AUX_RESET_DONE, aux110->mask->AUX_RESET_DONE
, 0, 1, 11, __func__, 151)
;
152 }
153 } /*if (field)*/
154
155 /* request SW to access AUX */
156 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1)generic_reg_update_ex(aux110->base.ctx, (aux110->regs->
AUX_ARB_CONTROL), 1, aux110->shift->AUX_SW_USE_AUX_REG_REQ
, aux110->mask->AUX_SW_USE_AUX_REG_REQ, 1)
;
157
158 value = REG_READ(AUX_ARB_CONTROL)dm_read_reg_func(aux110->base.ctx, (aux110->regs->AUX_ARB_CONTROL
), __func__)
;
159 field = get_reg_field_value(get_reg_field_value_ex( (value), 0xc, 0x2)
160 value,get_reg_field_value_ex( (value), 0xc, 0x2)
161 AUX_ARB_CONTROL,get_reg_field_value_ex( (value), 0xc, 0x2)
162 AUX_REG_RW_CNTL_STATUS)get_reg_field_value_ex( (value), 0xc, 0x2);
163
164 return (field == SW_CAN_ACCESS_AUX1);
165}
166
167#define COMPOSE_AUX_SW_DATA_16_20(command, address)((command) | ((0xF0000 & (address)) >> 16)) \
168 ((command) | ((0xF0000 & (address)) >> 16))
169
170#define COMPOSE_AUX_SW_DATA_8_15(address)((0xFF00 & (address)) >> 8) \
171 ((0xFF00 & (address)) >> 8)
172
173#define COMPOSE_AUX_SW_DATA_0_7(address)(0xFF & (address)) \
174 (0xFF & (address))
175
176static void submit_channel_request(
177 struct dce_aux *engine,
178 struct aux_request_transaction_data *request)
179{
180 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine)({ const __typeof( ((struct aux_engine_dce110 *)0)->base )
*__mptr = ((engine)); (struct aux_engine_dce110 *)( (char *)
__mptr - __builtin_offsetof(struct aux_engine_dce110, base) )
;})
;
181 uint32_t value;
182 uint32_t length;
183
184 bool_Bool is_write =
185 ((request->type == AUX_TRANSACTION_TYPE_DP) &&
186 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) ||
187 ((request->type == AUX_TRANSACTION_TYPE_I2C) &&
188 ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
189 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT)));
190 if (REG(AUXN_IMPCAL)(aux110->regs->AUXN_IMPCAL)) {
191 /* clear_aux_error */
192 REG_UPDATE_SEQ_2(AUXN_IMPCAL,{ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUXN_IMPCAL), 1, aux110->shift->AUXN_CALOUT_ERROR_AK
, aux110->mask->AUXN_CALOUT_ERROR_AK, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUXN_IMPCAL), val,
1, aux110->shift->AUXN_CALOUT_ERROR_AK, aux110->mask
->AUXN_CALOUT_ERROR_AK, 0); }
193 AUXN_CALOUT_ERROR_AK, 1,{ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUXN_IMPCAL), 1, aux110->shift->AUXN_CALOUT_ERROR_AK
, aux110->mask->AUXN_CALOUT_ERROR_AK, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUXN_IMPCAL), val,
1, aux110->shift->AUXN_CALOUT_ERROR_AK, aux110->mask
->AUXN_CALOUT_ERROR_AK, 0); }
194 AUXN_CALOUT_ERROR_AK, 0){ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUXN_IMPCAL), 1, aux110->shift->AUXN_CALOUT_ERROR_AK
, aux110->mask->AUXN_CALOUT_ERROR_AK, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUXN_IMPCAL), val,
1, aux110->shift->AUXN_CALOUT_ERROR_AK, aux110->mask
->AUXN_CALOUT_ERROR_AK, 0); }
;
195
196 REG_UPDATE_SEQ_2(AUXP_IMPCAL,{ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUXP_IMPCAL), 1, aux110->shift->AUXP_CALOUT_ERROR_AK
, aux110->mask->AUXP_CALOUT_ERROR_AK, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUXP_IMPCAL), val,
1, aux110->shift->AUXP_CALOUT_ERROR_AK, aux110->mask
->AUXP_CALOUT_ERROR_AK, 0); }
197 AUXP_CALOUT_ERROR_AK, 1,{ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUXP_IMPCAL), 1, aux110->shift->AUXP_CALOUT_ERROR_AK
, aux110->mask->AUXP_CALOUT_ERROR_AK, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUXP_IMPCAL), val,
1, aux110->shift->AUXP_CALOUT_ERROR_AK, aux110->mask
->AUXP_CALOUT_ERROR_AK, 0); }
198 AUXP_CALOUT_ERROR_AK, 0){ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUXP_IMPCAL), 1, aux110->shift->AUXP_CALOUT_ERROR_AK
, aux110->mask->AUXP_CALOUT_ERROR_AK, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUXP_IMPCAL), val,
1, aux110->shift->AUXP_CALOUT_ERROR_AK, aux110->mask
->AUXP_CALOUT_ERROR_AK, 0); }
;
199
200 /* force_default_calibrate */
201 REG_UPDATE_SEQ_2(AUXN_IMPCAL,{ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUXN_IMPCAL), 1, aux110->shift->AUXN_IMPCAL_ENABLE
, aux110->mask->AUXN_IMPCAL_ENABLE, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUXN_IMPCAL), val,
1, aux110->shift->AUXN_IMPCAL_OVERRIDE_ENABLE, aux110->
mask->AUXN_IMPCAL_OVERRIDE_ENABLE, 0); }
202 AUXN_IMPCAL_ENABLE, 1,{ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUXN_IMPCAL), 1, aux110->shift->AUXN_IMPCAL_ENABLE
, aux110->mask->AUXN_IMPCAL_ENABLE, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUXN_IMPCAL), val,
1, aux110->shift->AUXN_IMPCAL_OVERRIDE_ENABLE, aux110->
mask->AUXN_IMPCAL_OVERRIDE_ENABLE, 0); }
203 AUXN_IMPCAL_OVERRIDE_ENABLE, 0){ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUXN_IMPCAL), 1, aux110->shift->AUXN_IMPCAL_ENABLE
, aux110->mask->AUXN_IMPCAL_ENABLE, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUXN_IMPCAL), val,
1, aux110->shift->AUXN_IMPCAL_OVERRIDE_ENABLE, aux110->
mask->AUXN_IMPCAL_OVERRIDE_ENABLE, 0); }
;
204
205 /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */
206
207 REG_UPDATE_SEQ_2(AUXP_IMPCAL,{ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUXP_IMPCAL), 1, aux110->shift->AUXP_IMPCAL_OVERRIDE_ENABLE
, aux110->mask->AUXP_IMPCAL_OVERRIDE_ENABLE, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUXP_IMPCAL), val,
1, aux110->shift->AUXP_IMPCAL_OVERRIDE_ENABLE, aux110->
mask->AUXP_IMPCAL_OVERRIDE_ENABLE, 0); }
208 AUXP_IMPCAL_OVERRIDE_ENABLE, 1,{ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUXP_IMPCAL), 1, aux110->shift->AUXP_IMPCAL_OVERRIDE_ENABLE
, aux110->mask->AUXP_IMPCAL_OVERRIDE_ENABLE, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUXP_IMPCAL), val,
1, aux110->shift->AUXP_IMPCAL_OVERRIDE_ENABLE, aux110->
mask->AUXP_IMPCAL_OVERRIDE_ENABLE, 0); }
209 AUXP_IMPCAL_OVERRIDE_ENABLE, 0){ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUXP_IMPCAL), 1, aux110->shift->AUXP_IMPCAL_OVERRIDE_ENABLE
, aux110->mask->AUXP_IMPCAL_OVERRIDE_ENABLE, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUXP_IMPCAL), val,
1, aux110->shift->AUXP_IMPCAL_OVERRIDE_ENABLE, aux110->
mask->AUXP_IMPCAL_OVERRIDE_ENABLE, 0); }
;
210 }
211
212 REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1)generic_reg_update_ex(aux110->base.ctx, (aux110->regs->
AUX_INTERRUPT_CONTROL), 1, aux110->shift->AUX_SW_DONE_ACK
, aux110->mask->AUX_SW_DONE_ACK, 1)
;
213
214 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0,generic_reg_wait(aux110->base.ctx, (aux110->regs->AUX_SW_STATUS
), aux110->shift->AUX_SW_DONE, aux110->mask->AUX_SW_DONE
, 0, 10, aux110->polling_timeout_period/10, __func__, 215)
215 10, aux110->polling_timeout_period/10)generic_reg_wait(aux110->base.ctx, (aux110->regs->AUX_SW_STATUS
), aux110->shift->AUX_SW_DONE, aux110->mask->AUX_SW_DONE
, 0, 10, aux110->polling_timeout_period/10, __func__, 215)
;
216
217 /* set the delay and the number of bytes to write */
218
219 /* The length include
220 * the 4 bit header and the 20 bit address
221 * (that is 3 byte).
222 * If the requested length is non zero this means
223 * an addition byte specifying the length is required.
224 */
225
226 length = request->length ? 4 : 3;
227 if (is_write)
228 length += request->length;
229
230 REG_UPDATE_2(AUX_SW_CONTROL,generic_reg_update_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_CONTROL), 2, aux110->shift->AUX_SW_START_DELAY, aux110
->mask->AUX_SW_START_DELAY, request->delay, aux110->
shift->AUX_SW_WR_BYTES, aux110->mask->AUX_SW_WR_BYTES
, length)
231 AUX_SW_START_DELAY, request->delay,generic_reg_update_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_CONTROL), 2, aux110->shift->AUX_SW_START_DELAY, aux110
->mask->AUX_SW_START_DELAY, request->delay, aux110->
shift->AUX_SW_WR_BYTES, aux110->mask->AUX_SW_WR_BYTES
, length)
232 AUX_SW_WR_BYTES, length)generic_reg_update_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_CONTROL), 2, aux110->shift->AUX_SW_START_DELAY, aux110
->mask->AUX_SW_START_DELAY, request->delay, aux110->
shift->AUX_SW_WR_BYTES, aux110->mask->AUX_SW_WR_BYTES
, length)
;
233
234 /* program action and address and payload data (if 'is_write') */
235 value = REG_UPDATE_4(AUX_SW_DATA,generic_reg_update_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), 4, aux110->shift->AUX_SW_INDEX, aux110->
mask->AUX_SW_INDEX, 0, aux110->shift->AUX_SW_DATA_RW
, aux110->mask->AUX_SW_DATA_RW, 0, aux110->shift->
AUX_SW_AUTOINCREMENT_DISABLE, aux110->mask->AUX_SW_AUTOINCREMENT_DISABLE
, 1, aux110->shift->AUX_SW_DATA, aux110->mask->AUX_SW_DATA
, ((request->action) | ((0xF0000 & (request->address
)) >> 16)))
236 AUX_SW_INDEX, 0,generic_reg_update_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), 4, aux110->shift->AUX_SW_INDEX, aux110->
mask->AUX_SW_INDEX, 0, aux110->shift->AUX_SW_DATA_RW
, aux110->mask->AUX_SW_DATA_RW, 0, aux110->shift->
AUX_SW_AUTOINCREMENT_DISABLE, aux110->mask->AUX_SW_AUTOINCREMENT_DISABLE
, 1, aux110->shift->AUX_SW_DATA, aux110->mask->AUX_SW_DATA
, ((request->action) | ((0xF0000 & (request->address
)) >> 16)))
237 AUX_SW_DATA_RW, 0,generic_reg_update_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), 4, aux110->shift->AUX_SW_INDEX, aux110->
mask->AUX_SW_INDEX, 0, aux110->shift->AUX_SW_DATA_RW
, aux110->mask->AUX_SW_DATA_RW, 0, aux110->shift->
AUX_SW_AUTOINCREMENT_DISABLE, aux110->mask->AUX_SW_AUTOINCREMENT_DISABLE
, 1, aux110->shift->AUX_SW_DATA, aux110->mask->AUX_SW_DATA
, ((request->action) | ((0xF0000 & (request->address
)) >> 16)))
238 AUX_SW_AUTOINCREMENT_DISABLE, 1,generic_reg_update_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), 4, aux110->shift->AUX_SW_INDEX, aux110->
mask->AUX_SW_INDEX, 0, aux110->shift->AUX_SW_DATA_RW
, aux110->mask->AUX_SW_DATA_RW, 0, aux110->shift->
AUX_SW_AUTOINCREMENT_DISABLE, aux110->mask->AUX_SW_AUTOINCREMENT_DISABLE
, 1, aux110->shift->AUX_SW_DATA, aux110->mask->AUX_SW_DATA
, ((request->action) | ((0xF0000 & (request->address
)) >> 16)))
239 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address))generic_reg_update_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), 4, aux110->shift->AUX_SW_INDEX, aux110->
mask->AUX_SW_INDEX, 0, aux110->shift->AUX_SW_DATA_RW
, aux110->mask->AUX_SW_DATA_RW, 0, aux110->shift->
AUX_SW_AUTOINCREMENT_DISABLE, aux110->mask->AUX_SW_AUTOINCREMENT_DISABLE
, 1, aux110->shift->AUX_SW_DATA, aux110->mask->AUX_SW_DATA
, ((request->action) | ((0xF0000 & (request->address
)) >> 16)))
;
240
241 value = REG_SET_2(AUX_SW_DATA, value,generic_reg_set_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), value, 2, aux110->shift->AUX_SW_AUTOINCREMENT_DISABLE
, aux110->mask->AUX_SW_AUTOINCREMENT_DISABLE, 0, aux110
->shift->AUX_SW_DATA, aux110->mask->AUX_SW_DATA, (
(0xFF00 & (request->address)) >> 8))
242 AUX_SW_AUTOINCREMENT_DISABLE, 0,generic_reg_set_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), value, 2, aux110->shift->AUX_SW_AUTOINCREMENT_DISABLE
, aux110->mask->AUX_SW_AUTOINCREMENT_DISABLE, 0, aux110
->shift->AUX_SW_DATA, aux110->mask->AUX_SW_DATA, (
(0xFF00 & (request->address)) >> 8))
243 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address))generic_reg_set_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), value, 2, aux110->shift->AUX_SW_AUTOINCREMENT_DISABLE
, aux110->mask->AUX_SW_AUTOINCREMENT_DISABLE, 0, aux110
->shift->AUX_SW_DATA, aux110->mask->AUX_SW_DATA, (
(0xFF00 & (request->address)) >> 8))
;
244
245 value = REG_SET(AUX_SW_DATA, value,generic_reg_set_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), value, 1, aux110->shift->AUX_SW_DATA, aux110
->mask->AUX_SW_DATA, (0xFF & (request->address))
)
246 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address))generic_reg_set_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), value, 1, aux110->shift->AUX_SW_DATA, aux110
->mask->AUX_SW_DATA, (0xFF & (request->address))
)
;
247
248 if (request->length) {
249 value = REG_SET(AUX_SW_DATA, value,generic_reg_set_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), value, 1, aux110->shift->AUX_SW_DATA, aux110
->mask->AUX_SW_DATA, request->length - 1)
250 AUX_SW_DATA, request->length - 1)generic_reg_set_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), value, 1, aux110->shift->AUX_SW_DATA, aux110
->mask->AUX_SW_DATA, request->length - 1)
;
251 }
252
253 if (is_write) {
254 /* Load the HW buffer with the Data to be sent.
255 * This is relevant for write operation.
256 * For read, the data recived data will be
257 * processed in process_channel_reply().
258 */
259 uint32_t i = 0;
260
261 while (i < request->length) {
262 value = REG_SET(AUX_SW_DATA, value,generic_reg_set_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), value, 1, aux110->shift->AUX_SW_DATA, aux110
->mask->AUX_SW_DATA, request->data[i])
263 AUX_SW_DATA, request->data[i])generic_reg_set_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_DATA), value, 1, aux110->shift->AUX_SW_DATA, aux110
->mask->AUX_SW_DATA, request->data[i])
;
264
265 ++i;
266 }
267 }
268
269 REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1)generic_reg_update_ex(aux110->base.ctx, (aux110->regs->
AUX_SW_CONTROL), 1, aux110->shift->AUX_SW_GO, aux110->
mask->AUX_SW_GO, 1)
;
270 EVENT_LOG_AUX_REQ(engine->ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_NATIVE,
271 request->action, request->address, request->length, request->data);
272}
273
274static int read_channel_reply(struct dce_aux *engine, uint32_t size,
275 uint8_t *buffer, uint8_t *reply_result,
276 uint32_t *sw_status)
277{
278 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine)({ const __typeof( ((struct aux_engine_dce110 *)0)->base )
*__mptr = ((engine)); (struct aux_engine_dce110 *)( (char *)
__mptr - __builtin_offsetof(struct aux_engine_dce110, base) )
;})
;
279 uint32_t bytes_replied;
280 uint32_t reply_result_32;
281
282 *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT,generic_reg_get(aux110->base.ctx, (aux110->regs->AUX_SW_STATUS
), aux110->shift->AUX_SW_REPLY_BYTE_COUNT, aux110->mask
->AUX_SW_REPLY_BYTE_COUNT, &bytes_replied)
283 &bytes_replied)generic_reg_get(aux110->base.ctx, (aux110->regs->AUX_SW_STATUS
), aux110->shift->AUX_SW_REPLY_BYTE_COUNT, aux110->mask
->AUX_SW_REPLY_BYTE_COUNT, &bytes_replied)
;
284
285 /* In case HPD is LOW, exit AUX transaction */
286 if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK0x200))
287 return -1;
288
289 /* Need at least the status byte */
290 if (!bytes_replied)
291 return -1;
292
293 REG_UPDATE_SEQ_3(AUX_SW_DATA,{ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUX_SW_DATA), 1, aux110->shift->AUX_SW_INDEX
, aux110->mask->AUX_SW_INDEX, 0); val = generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUX_SW_DATA), val,
1, aux110->shift->AUX_SW_AUTOINCREMENT_DISABLE, aux110
->mask->AUX_SW_AUTOINCREMENT_DISABLE, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUX_SW_DATA), val,
1, aux110->shift->AUX_SW_DATA_RW, aux110->mask->
AUX_SW_DATA_RW, 1); }
294 AUX_SW_INDEX, 0,{ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUX_SW_DATA), 1, aux110->shift->AUX_SW_INDEX
, aux110->mask->AUX_SW_INDEX, 0); val = generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUX_SW_DATA), val,
1, aux110->shift->AUX_SW_AUTOINCREMENT_DISABLE, aux110
->mask->AUX_SW_AUTOINCREMENT_DISABLE, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUX_SW_DATA), val,
1, aux110->shift->AUX_SW_DATA_RW, aux110->mask->
AUX_SW_DATA_RW, 1); }
295 AUX_SW_AUTOINCREMENT_DISABLE, 1,{ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUX_SW_DATA), 1, aux110->shift->AUX_SW_INDEX
, aux110->mask->AUX_SW_INDEX, 0); val = generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUX_SW_DATA), val,
1, aux110->shift->AUX_SW_AUTOINCREMENT_DISABLE, aux110
->mask->AUX_SW_AUTOINCREMENT_DISABLE, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUX_SW_DATA), val,
1, aux110->shift->AUX_SW_DATA_RW, aux110->mask->
AUX_SW_DATA_RW, 1); }
296 AUX_SW_DATA_RW, 1){ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUX_SW_DATA), 1, aux110->shift->AUX_SW_INDEX
, aux110->mask->AUX_SW_INDEX, 0); val = generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUX_SW_DATA), val,
1, aux110->shift->AUX_SW_AUTOINCREMENT_DISABLE, aux110
->mask->AUX_SW_AUTOINCREMENT_DISABLE, 1); generic_reg_set_ex
(aux110->base.ctx, (aux110->regs->AUX_SW_DATA), val,
1, aux110->shift->AUX_SW_DATA_RW, aux110->mask->
AUX_SW_DATA_RW, 1); }
;
297
298 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32)generic_reg_get(aux110->base.ctx, (aux110->regs->AUX_SW_DATA
), aux110->shift->AUX_SW_DATA, aux110->mask->AUX_SW_DATA
, &reply_result_32)
;
299 reply_result_32 = reply_result_32 >> 4;
300 if (reply_result != NULL((void *)0))
301 *reply_result = (uint8_t)reply_result_32;
302
303 if (reply_result_32 == 0) { /* ACK */
304 uint32_t i = 0;
305
306 /* First byte was already used to get the command status */
307 --bytes_replied;
308
309 /* Do not overflow buffer */
310 if (bytes_replied > size)
311 return -1;
312
313 while (i < bytes_replied) {
314 uint32_t aux_sw_data_val;
315
316 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val)generic_reg_get(aux110->base.ctx, (aux110->regs->AUX_SW_DATA
), aux110->shift->AUX_SW_DATA, aux110->mask->AUX_SW_DATA
, &aux_sw_data_val)
;
317 buffer[i] = aux_sw_data_val;
318 ++i;
319 }
320
321 return i;
322 }
323
324 return 0;
325}
326
327static enum aux_channel_operation_result get_channel_status(
328 struct dce_aux *engine,
329 uint8_t *returned_bytes)
330{
331 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine)({ const __typeof( ((struct aux_engine_dce110 *)0)->base )
*__mptr = ((engine)); (struct aux_engine_dce110 *)( (char *)
__mptr - __builtin_offsetof(struct aux_engine_dce110, base) )
;})
;
332
333 uint32_t value;
334
335 if (returned_bytes == NULL((void *)0)) {
336 /*caller pass NULL pointer*/
337 ASSERT_CRITICAL(false)do { if (({ int __ret = !!(!(0)); if (__ret) printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/dce/dce_aux.c"
, 337); __builtin_expect(!!(__ret), 0); })) do {} while (0); }
while (0)
;
338 return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN;
339 }
340 *returned_bytes = 0;
341
342 /* poll to make sure that SW_DONE is asserted */
343 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1,generic_reg_wait(aux110->base.ctx, (aux110->regs->AUX_SW_STATUS
), aux110->shift->AUX_SW_DONE, aux110->mask->AUX_SW_DONE
, 1, 10, aux110->polling_timeout_period/10, __func__, 344)
344 10, aux110->polling_timeout_period/10)generic_reg_wait(aux110->base.ctx, (aux110->regs->AUX_SW_STATUS
), aux110->shift->AUX_SW_DONE, aux110->mask->AUX_SW_DONE
, 1, 10, aux110->polling_timeout_period/10, __func__, 344)
;
345
346 value = REG_READ(AUX_SW_STATUS)dm_read_reg_func(aux110->base.ctx, (aux110->regs->AUX_SW_STATUS
), __func__)
;
347 /* in case HPD is LOW, exit AUX transaction */
348 if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK0x200))
349 return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
350
351 /* Note that the following bits are set in 'status.bits'
352 * during CTS 4.2.1.2 (FW 3.3.1):
353 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP,
354 * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H.
355 *
356 * AUX_SW_RX_MIN_COUNT_VIOL is an internal,
357 * HW debugging bit and should be ignored.
358 */
359 if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK0x1) {
360 if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK0x70) ||
361 (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK0x80))
362 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
363
364 else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK0x4000) ||
365 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK0x100000) ||
366 (value &
367 AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK0x400000) ||
368 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK0x800000))
369 return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
370
371 *returned_bytes = get_reg_field_value(value,get_reg_field_value_ex( (value), 0x1f000000, 0x18)
372 AUX_SW_STATUS,get_reg_field_value_ex( (value), 0x1f000000, 0x18)
373 AUX_SW_REPLY_BYTE_COUNT)get_reg_field_value_ex( (value), 0x1f000000, 0x18);
374
375 if (*returned_bytes == 0)
376 return
377 AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY;
378 else {
379 *returned_bytes -= 1;
380 return AUX_CHANNEL_OPERATION_SUCCEEDED;
381 }
382 } else {
383 /*time_elapsed >= aux_engine->timeout_period
384 * AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point
385 */
386 ASSERT_CRITICAL(false)do { if (({ int __ret = !!(!(0)); if (__ret) printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/dce/dce_aux.c"
, 386); __builtin_expect(!!(__ret), 0); })) do {} while (0); }
while (0)
;
387 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT;
388 }
389}
390
391enum i2caux_engine_type get_engine_type(
392 const struct dce_aux *engine)
393{
394 return I2CAUX_ENGINE_TYPE_AUX;
395}
396
397static bool_Bool acquire(
398 struct dce_aux *engine,
399 struct ddc *ddc)
400{
401 enum gpio_result result;
402
403 if ((engine == NULL((void *)0)) || !is_engine_available(engine))
404 return false0;
405
406 result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
407 GPIO_DDC_CONFIG_TYPE_MODE_AUX);
408
409 if (result != GPIO_RESULT_OK)
410 return false0;
411
412 if (!acquire_engine(engine)) {
413 dal_ddc_close(ddc);
414 return false0;
415 }
416
417 engine->ddc = ddc;
418
419 return true1;
420}
421
422void dce110_engine_destroy(struct dce_aux **engine)
423{
424
425 struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine)({ const __typeof( ((struct aux_engine_dce110 *)0)->base )
*__mptr = ((*engine)); (struct aux_engine_dce110 *)( (char *
)__mptr - __builtin_offsetof(struct aux_engine_dce110, base) )
;})
;
426
427 kfree(engine110);
428 *engine = NULL((void *)0);
429
430}
431
432static uint32_t dce_aux_configure_timeout(struct ddc_service *ddc,
433 uint32_t timeout_in_us)
434{
435 uint32_t multiplier = 0;
436 uint32_t length = 0;
437 uint32_t prev_length = 0;
438 uint32_t prev_mult = 0;
439 uint32_t prev_timeout_val = 0;
440 struct ddc *ddc_pin = ddc->ddc_pin;
441 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
442 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine)({ const __typeof( ((struct aux_engine_dce110 *)0)->base )
*__mptr = ((aux_engine)); (struct aux_engine_dce110 *)( (char
*)__mptr - __builtin_offsetof(struct aux_engine_dce110, base
) );})
;
443
444 /* 1-Update polling timeout period */
445 aux110->polling_timeout_period = timeout_in_us * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER;
446
447 /* 2-Update aux timeout period length and multiplier */
448 if (timeout_in_us == 0) {
449 multiplier = DEFAULT_AUX_ENGINE_MULT0;
450 length = DEFAULT_AUX_ENGINE_LENGTH69;
451 } else if (timeout_in_us <= TIME_OUT_INCREMENT1016) {
452 multiplier = 0;
453 length = timeout_in_us/TIME_OUT_MULTIPLIER_88;
454 if (timeout_in_us % TIME_OUT_MULTIPLIER_88 != 0)
455 length++;
456 } else if (timeout_in_us <= 2 * TIME_OUT_INCREMENT1016) {
457 multiplier = 1;
458 length = timeout_in_us/TIME_OUT_MULTIPLIER_1616;
459 if (timeout_in_us % TIME_OUT_MULTIPLIER_1616 != 0)
460 length++;
461 } else if (timeout_in_us <= 4 * TIME_OUT_INCREMENT1016) {
462 multiplier = 2;
463 length = timeout_in_us/TIME_OUT_MULTIPLIER_3232;
464 if (timeout_in_us % TIME_OUT_MULTIPLIER_3232 != 0)
465 length++;
466 } else if (timeout_in_us > 4 * TIME_OUT_INCREMENT1016) {
467 multiplier = 3;
468 length = timeout_in_us/TIME_OUT_MULTIPLIER_6464;
469 if (timeout_in_us % TIME_OUT_MULTIPLIER_6464 != 0)
470 length++;
471 }
472
473 length = (length < MAX_TIMEOUT_LENGTH127) ? length : MAX_TIMEOUT_LENGTH127;
474
475 REG_GET_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, &prev_length, AUX_RX_TIMEOUT_LEN_MUL, &prev_mult)generic_reg_get2(aux110->base.ctx, (aux110->regs->AUX_DPHY_RX_CONTROL1
), aux110->shift->AUX_RX_TIMEOUT_LEN, aux110->mask->
AUX_RX_TIMEOUT_LEN, &prev_length, aux110->shift->AUX_RX_TIMEOUT_LEN_MUL
, aux110->mask->AUX_RX_TIMEOUT_LEN_MUL, &prev_mult)
;
476
477 switch (prev_mult) {
478 case 0:
479 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_88;
480 break;
481 case 1:
482 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_1616;
483 break;
484 case 2:
485 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_3232;
486 break;
487 case 3:
488 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_6464;
489 break;
490 default:
491 prev_timeout_val = DEFAULT_AUX_ENGINE_LENGTH69 * TIME_OUT_MULTIPLIER_88;
492 break;
493 }
494
495 REG_UPDATE_SEQ_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, length, AUX_RX_TIMEOUT_LEN_MUL, multiplier){ uint32_t val = generic_reg_update_ex(aux110->base.ctx, (
aux110->regs->AUX_DPHY_RX_CONTROL1), 1, aux110->shift
->AUX_RX_TIMEOUT_LEN, aux110->mask->AUX_RX_TIMEOUT_LEN
, length); generic_reg_set_ex(aux110->base.ctx, (aux110->
regs->AUX_DPHY_RX_CONTROL1), val, 1, aux110->shift->
AUX_RX_TIMEOUT_LEN_MUL, aux110->mask->AUX_RX_TIMEOUT_LEN_MUL
, multiplier); }
;
496
497 return prev_timeout_val;
498}
499
500static struct dce_aux_funcs aux_functions = {
501 .configure_timeout = NULL((void *)0),
502 .destroy = NULL((void *)0),
503};
504
505struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110,
506 struct dc_context *ctx,
507 uint32_t inst,
508 uint32_t timeout_period,
509 const struct dce110_aux_registers *regs,
510 const struct dce110_aux_registers_mask *mask,
511 const struct dce110_aux_registers_shift *shift,
512 bool_Bool is_ext_aux_timeout_configurable)
513{
514 aux_engine110->base.ddc = NULL((void *)0);
515 aux_engine110->base.ctx = ctx;
516 aux_engine110->base.delay = 0;
517 aux_engine110->base.max_defer_write_retry = 0;
518 aux_engine110->base.inst = inst;
519 aux_engine110->polling_timeout_period = timeout_period;
520 aux_engine110->regs = regs;
521
522 aux_engine110->mask = mask;
523 aux_engine110->shift = shift;
524 aux_engine110->base.funcs = &aux_functions;
525 if (is_ext_aux_timeout_configurable)
526 aux_engine110->base.funcs->configure_timeout = &dce_aux_configure_timeout;
527
528 return &aux_engine110->base;
529}
530
531static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payload *payload)
532{
533 if (payload->i2c_over_aux) {
534 if (payload->write) {
535 if (payload->mot)
536 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT;
537 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
538 }
539 if (payload->mot)
540 return I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT;
541 return I2CAUX_TRANSACTION_ACTION_I2C_READ;
542 }
543 if (payload->write)
544 return I2CAUX_TRANSACTION_ACTION_DP_WRITE;
545 return I2CAUX_TRANSACTION_ACTION_DP_READ;
546}
547
548int dce_aux_transfer_raw(struct ddc_service *ddc,
549 struct aux_payload *payload,
550 enum aux_channel_operation_result *operation_result)
551{
552 struct ddc *ddc_pin = ddc->ddc_pin;
553 struct dce_aux *aux_engine;
554 struct aux_request_transaction_data aux_req;
555 struct aux_reply_transaction_data aux_rep;
556 uint8_t returned_bytes = 0;
557 int res = -1;
558 uint32_t status;
559
560 memset(&aux_req, 0, sizeof(aux_req))__builtin_memset((&aux_req), (0), (sizeof(aux_req)));
561 memset(&aux_rep, 0, sizeof(aux_rep))__builtin_memset((&aux_rep), (0), (sizeof(aux_rep)));
562
563 aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
564 if (!acquire(aux_engine, ddc_pin)) {
565 *operation_result = AUX_CHANNEL_OPERATION_FAILED_ENGINE_ACQUIRE;
566 return -1;
567 }
568
569 if (payload->i2c_over_aux)
570 aux_req.type = AUX_TRANSACTION_TYPE_I2C;
571 else
572 aux_req.type = AUX_TRANSACTION_TYPE_DP;
573
574 aux_req.action = i2caux_action_from_payload(payload);
575
576 aux_req.address = payload->address;
577 aux_req.delay = 0;
578 aux_req.length = payload->length;
579 aux_req.data = payload->data;
580
581 submit_channel_request(aux_engine, &aux_req);
582 *operation_result = get_channel_status(aux_engine, &returned_bytes);
583
584 if (*operation_result == AUX_CHANNEL_OPERATION_SUCCEEDED) {
585 int bytes_replied = 0;
586 bytes_replied = read_channel_reply(aux_engine, payload->length,
Value stored to 'bytes_replied' is never read
587 payload->data, payload->reply,
588 &status);
589 EVENT_LOG_AUX_REP(aux_engine->ddc->pin_data->en,
590 EVENT_LOG_AUX_ORIGIN_NATIVE, *payload->reply,
591 bytes_replied, payload->data);
592 res = returned_bytes;
593 } else {
594 res = -1;
595 }
596
597 release_engine(aux_engine);
598 return res;
599}
600
601#define AUX_MAX_RETRIES7 7
602#define AUX_MAX_DEFER_RETRIES7 7
603#define AUX_MAX_I2C_DEFER_RETRIES7 7
604#define AUX_MAX_INVALID_REPLY_RETRIES2 2
605#define AUX_MAX_TIMEOUT_RETRIES3 3
606
607bool_Bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
608 struct aux_payload *payload)
609{
610 int i, ret = 0;
611 uint8_t reply;
612 bool_Bool payload_reply = true1;
613 enum aux_channel_operation_result operation_result;
614 bool_Bool retry_on_defer = false0;
615
616 int aux_ack_retries = 0,
617 aux_defer_retries = 0,
618 aux_i2c_defer_retries = 0,
619 aux_timeout_retries = 0,
620 aux_invalid_reply_retries = 0;
621
622 if (!payload->reply) {
623 payload_reply = false0;
624 payload->reply = &reply;
625 }
626
627 for (i = 0; i < AUX_MAX_RETRIES7; i++) {
628 ret = dce_aux_transfer_raw(ddc, payload, &operation_result);
629 switch (operation_result) {
630 case AUX_CHANNEL_OPERATION_SUCCEEDED:
631 aux_timeout_retries = 0;
632 aux_invalid_reply_retries = 0;
633
634 switch (*payload->reply) {
635 case AUX_TRANSACTION_REPLY_AUX_ACK:
636 if (!payload->write && payload->length != ret) {
637 if (++aux_ack_retries >= AUX_MAX_RETRIES7)
638 goto fail;
639 else
640 udelay(300);
641 } else
642 return true1;
643 break;
644
645 case AUX_TRANSACTION_REPLY_AUX_DEFER:
646 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER:
647 retry_on_defer = true1;
648 fallthroughdo {} while (0);
649 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
650 if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES7) {
651 goto fail;
652 } else {
653 if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) ||
654 (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) {
655 if (payload->defer_delay > 0)
656 drm_msleep(payload->defer_delay)mdelay(payload->defer_delay);
657 }
658 }
659 break;
660
661 case AUX_TRANSACTION_REPLY_I2C_DEFER:
662 aux_defer_retries = 0;
663 if (++aux_i2c_defer_retries >= AUX_MAX_I2C_DEFER_RETRIES7)
664 goto fail;
665 break;
666
667 case AUX_TRANSACTION_REPLY_AUX_NACK:
668 case AUX_TRANSACTION_REPLY_HPD_DISCON:
669 default:
670 goto fail;
671 }
672 break;
673
674 case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY:
675 if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES2)
676 goto fail;
677 else
678 udelay(400);
679 break;
680
681 case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
682 // Check whether a DEFER had occurred before the timeout.
683 // If so, treat timeout as a DEFER.
684 if (retry_on_defer) {
685 if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES7)
686 goto fail;
687 else if (payload->defer_delay > 0)
688 drm_msleep(payload->defer_delay)mdelay(payload->defer_delay);
689 } else {
690 if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES3)
691 goto fail;
692 else {
693 /*
694 * DP 1.4, 2.8.2: AUX Transaction Response/Reply Timeouts
695 * According to the DP spec there should be 3 retries total
696 * with a 400us wait inbetween each. Hardware already waits
697 * for 550us therefore no wait is required here.
698 */
699 }
700 }
701 break;
702
703 case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON:
704 case AUX_CHANNEL_OPERATION_FAILED_ENGINE_ACQUIRE:
705 case AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN:
706 default:
707 goto fail;
708 }
709 }
710
711fail:
712 if (!payload_reply)
713 payload->reply = NULL((void *)0);
714 return false0;
715}