summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/arm/imx233/dcp-imx233.c87
-rw-r--r--firmware/target/arm/imx233/dcp-imx233.h8
2 files changed, 77 insertions, 18 deletions
diff --git a/firmware/target/arm/imx233/dcp-imx233.c b/firmware/target/arm/imx233/dcp-imx233.c
index 565dba7691..f7849b183f 100644
--- a/firmware/target/arm/imx233/dcp-imx233.c
+++ b/firmware/target/arm/imx233/dcp-imx233.c
@@ -111,44 +111,98 @@ static enum imx233_dcp_error_t get_error_status(int ch)
111 } 111 }
112} 112}
113 113
114enum imx233_dcp_error_t imx233_dcp_memcpy_ex(int ch, void *src, void *dst, size_t len) 114static enum imx233_dcp_error_t imx233_dcp_job(int ch)
115{ 115{
116 /* if IRQs are not enabled, don't enable channel interrupt and do some polling */
117 bool irq_enabled = irq_enabled();
116 /* enable channel, clear interrupt, enable interrupt */ 118 /* enable channel, clear interrupt, enable interrupt */
117 imx233_enable_interrupt(INT_SRC_DCP, true); 119 imx233_enable_interrupt(INT_SRC_DCP, true);
118 __REG_SET(HW_DCP_CTRL) = HW_DCP_CTRL__CHANNEL_INTERRUPT_ENABLE(ch); 120 if(irq_enabled)
121 __REG_SET(HW_DCP_CTRL) = HW_DCP_CTRL__CHANNEL_INTERRUPT_ENABLE(ch);
119 __REG_CLR(HW_DCP_STAT) = HW_DCP_STAT__IRQ(ch); 122 __REG_CLR(HW_DCP_STAT) = HW_DCP_STAT__IRQ(ch);
120 __REG_SET(HW_DCP_CHANNELCTRL) = HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(ch); 123 __REG_SET(HW_DCP_CHANNELCTRL) = HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(ch);
121 124
125 /* write back packet */
126 commit_discard_dcache_range(&channel_packet[ch], sizeof(struct imx233_dcp_packet_t));
127 /* write 1 to semaphore to run job */
128 HW_DCP_CHxCMDPTR(ch) = (uint32_t)PHYSICAL_ADDR(&channel_packet[ch]);
129 HW_DCP_CHxSEMA(ch) = 1;
130 /* wait completion */
131 if(irq_enabled)
132 semaphore_wait(&channel_sema[ch], TIMEOUT_BLOCK);
133 else
134 while(__XTRACT_EX(HW_DCP_CHxSEMA(ch), HW_DCP_CHxSEMA__VALUE))
135 udelay(10);
136 /* disable channel and interrupt */
137 __REG_CLR(HW_DCP_CTRL) = HW_DCP_CTRL__CHANNEL_INTERRUPT_ENABLE(ch);
138 __REG_CLR(HW_DCP_CHANNELCTRL) = HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(ch);
139 /* read status */
140 return get_error_status(ch);
141}
142
143
144enum imx233_dcp_error_t imx233_dcp_memcpy_ex(int ch, bool fill, const void *src, void *dst, size_t len)
145{
122 /* prepare packet */ 146 /* prepare packet */
123 channel_packet[ch].next = 0; 147 channel_packet[ch].next = 0;
124 channel_packet[ch].ctrl0 = HW_DCP_CTRL0__INTERRUPT_ENABLE | 148 channel_packet[ch].ctrl0 = HW_DCP_CTRL0__INTERRUPT_ENABLE |
125 HW_DCP_CTRL0__ENABLE_MEMCOPY | HW_DCP_CTRL0__DECR_SEMAPHORE; 149 HW_DCP_CTRL0__ENABLE_MEMCOPY | HW_DCP_CTRL0__DECR_SEMAPHORE |
150 (fill ? HW_DCP_CTRL0__CONSTANT_FILL : 0);
126 channel_packet[ch].ctrl1 = 0; 151 channel_packet[ch].ctrl1 = 0;
127 channel_packet[ch].src = (uint32_t)PHYSICAL_ADDR(src); 152 channel_packet[ch].src = (uint32_t)(fill ? src : PHYSICAL_ADDR(src));
128 channel_packet[ch].dst = (uint32_t)PHYSICAL_ADDR(dst); 153 channel_packet[ch].dst = (uint32_t)PHYSICAL_ADDR(dst);
129 channel_packet[ch].size = len; 154 channel_packet[ch].size = len;
130 channel_packet[ch].payload = 0; 155 channel_packet[ch].payload = 0;
131 channel_packet[ch].status = 0; 156 channel_packet[ch].status = 0;
132 157
133 /* write-back src, discard dst, write-back packet */ 158 /* write-back src if not filling, discard dst */
134 commit_discard_dcache_range(src, len); 159 if(!fill)
160 commit_discard_dcache_range(src, len);
135 discard_dcache_range(dst, len); 161 discard_dcache_range(dst, len);
136 commit_discard_dcache_range(&channel_packet[ch], sizeof(struct imx233_dcp_packet_t)); 162
137 /* write 1 to semaphore to run job */ 163 /* do the job */
138 HW_DCP_CHxCMDPTR(ch) = (uint32_t)PHYSICAL_ADDR(&channel_packet[ch]); 164 return imx233_dcp_job(ch);
139 HW_DCP_CHxSEMA(ch) = 1; 165}
140 /* wait completion */ 166
141 semaphore_wait(&channel_sema[ch], TIMEOUT_BLOCK); 167enum imx233_dcp_error_t imx233_dcp_memcpy(bool fill, const void *src, void *dst, size_t len, int tmo)
142 /* read status */ 168{
143 return get_error_status(ch); 169 int chan = imx233_dcp_acquire_channel(tmo);
170 if(chan == OBJ_WAIT_TIMEDOUT)
171 return DCP_TIMEOUT;
172 enum imx233_dcp_error_t err = imx233_dcp_memcpy_ex(chan, fill, src, dst, len);
173 imx233_dcp_release_channel(chan);
174 return err;
175}
176
177enum imx233_dcp_error_t imx233_dcp_blit_ex(int ch, bool fill, const void *src, size_t w, size_t h, void *dst, size_t out_w)
178{
179 /* prepare packet */
180 channel_packet[ch].next = 0;
181 channel_packet[ch].ctrl0 = HW_DCP_CTRL0__INTERRUPT_ENABLE |
182 HW_DCP_CTRL0__ENABLE_MEMCOPY | HW_DCP_CTRL0__DECR_SEMAPHORE |
183 HW_DCP_CTRL0__ENABLE_BLIT |
184 (fill ? HW_DCP_CTRL0__CONSTANT_FILL : 0);
185 channel_packet[ch].ctrl1 = out_w;
186 channel_packet[ch].src = (uint32_t)(fill ? src : PHYSICAL_ADDR(src));
187 channel_packet[ch].dst = (uint32_t)PHYSICAL_ADDR(dst);
188 channel_packet[ch].size = w | h << HW_DCP_SIZE__NUMBER_LINES_BP;
189 channel_packet[ch].payload = 0;
190 channel_packet[ch].status = 0;
191
192 /* we have a problem here to discard the output buffer since it's not contiguous
193 * so only commit the source */
194 if(!fill)
195 commit_discard_dcache_range(src, w * h);
196 /* do the job */
197 return imx233_dcp_job(ch);
144} 198}
145 199
146enum imx233_dcp_error_t imx233_dcp_memcpy(void *src, void *dst, size_t len, int tmo) 200enum imx233_dcp_error_t imx233_dcp_blit(bool fill, const void *src, size_t w, size_t h, void *dst, size_t out_w, int tmo)
147{ 201{
148 int chan = imx233_dcp_acquire_channel(tmo); 202 int chan = imx233_dcp_acquire_channel(tmo);
149 if(chan == OBJ_WAIT_TIMEDOUT) 203 if(chan == OBJ_WAIT_TIMEDOUT)
150 return DCP_TIMEOUT; 204 return DCP_TIMEOUT;
151 enum imx233_dcp_error_t err = imx233_dcp_memcpy_ex(chan, src, dst, len); 205 enum imx233_dcp_error_t err = imx233_dcp_blit_ex(chan, fill, src, w, h, dst, out_w);
152 imx233_dcp_release_channel(chan); 206 imx233_dcp_release_channel(chan);
153 return err; 207 return err;
154} 208}
@@ -185,6 +239,7 @@ struct imx233_dcp_info_t imx233_dcp_get_info(unsigned flags)
185 info.channel[i].enable = HW_DCP_CHANNELCTRL & HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(i); 239 info.channel[i].enable = HW_DCP_CHANNELCTRL & HW_DCP_CHANNELCTRL__ENABLE_CHANNEL(i);
186 info.channel[i].sema = __XTRACT_EX(HW_DCP_CHxSEMA(i), HW_DCP_CHxSEMA__VALUE); 240 info.channel[i].sema = __XTRACT_EX(HW_DCP_CHxSEMA(i), HW_DCP_CHxSEMA__VALUE);
187 info.channel[i].cmdptr = HW_DCP_CHxCMDPTR(i); 241 info.channel[i].cmdptr = HW_DCP_CHxCMDPTR(i);
242 info.channel[i].acquired = arbiter_acquired(&channel_arbiter, i);
188 } 243 }
189 } 244 }
190 if(flags & DCP_INFO_CSC) 245 if(flags & DCP_INFO_CSC)
diff --git a/firmware/target/arm/imx233/dcp-imx233.h b/firmware/target/arm/imx233/dcp-imx233.h
index 375da16c04..b8340fb4f0 100644
--- a/firmware/target/arm/imx233/dcp-imx233.h
+++ b/firmware/target/arm/imx233/dcp-imx233.h
@@ -295,6 +295,7 @@ struct imx233_dcp_channel_info_t
295 bool ready; 295 bool ready;
296 int sema; 296 int sema;
297 uint32_t cmdptr; 297 uint32_t cmdptr;
298 bool acquired;
298}; 299};
299 300
300struct imx233_dcp_csc_info_t 301struct imx233_dcp_csc_info_t
@@ -355,8 +356,11 @@ void imx233_dcp_release_channel(int chan);
355// doesn't check that channel is in use! 356// doesn't check that channel is in use!
356void imx233_dcp_reserve_channel(int channel); 357void imx233_dcp_reserve_channel(int channel);
357 358
358enum imx233_dcp_error_t imx233_dcp_memcpy_ex(int channel, void *src, void *dst, size_t len); 359enum imx233_dcp_error_t imx233_dcp_memcpy_ex(int channel, bool fill, const void *src, void *dst, size_t len);
359enum imx233_dcp_error_t imx233_dcp_memcpy(void *src, void *dst, size_t len, int tmo); 360enum imx233_dcp_error_t imx233_dcp_memcpy(bool fill, const void *src, void *dst, size_t len, int tmo);
361
362enum imx233_dcp_error_t imx233_dcp_blit_ex(int channel, bool fill, const void *src, size_t w, size_t h, void *dst, size_t out_w);
363enum imx233_dcp_error_t imx233_dcp_blit(bool fill, const void *src, size_t w, size_t h, void *dst, size_t out_w, int tmo);
360 364
361struct imx233_dcp_info_t imx233_dcp_get_info(unsigned flags); 365struct imx233_dcp_info_t imx233_dcp_get_info(unsigned flags);
362 366