Commit graph

39805 commits

Author SHA1 Message Date
Michael Giacomelli
deaef503bb opus: ARMv5E SILK resampler interpolation
On ARMv5E and later the fixed-phase FIR cycles at 8, 12 and 16 kHz load
two samples a word and take two coefficients a word from a literal
pool; smla<x><y> picks the halves, so an odd-aligned window costs
nothing.  Outputs are paired as two interleaved accumulator chains.  The
FIR buffer is now word aligned.  Generated by
silk/arm/gen_resampler_armv5e.py.  Bit-exact; OPUS_ARM_NO_SILK_ASM
disables it, and config.h sets that on M-profile cores.

Measured on the Clip+, silk_5.opus (WB SILK):
20.93 -> 15.84 MHz, -24.3%.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ibec71fd52542f768f22e2970c9f8c45118c708b9
2026-09-30 08:21:46 -04:00
Michael Giacomelli
15eec82d8f opus: ARMv4 SILK resampler interpolation
On ARMv4 the fixed-phase FIR cycles at 8, 12 and 16 kHz run as adds of
shifted samples rather than multiplies: every coefficient is a constant,
and a shifted add is one cycle where mla plus loading the coefficient is
five or six.  Each sample is loaded once per cycle and added into the
two or three outputs it feeds, sharing partial products such as 31x
between them, about 27 adds per output.  The kernels are generated by
silk/arm/gen_resampler_armv4.py.  Bit-exact; OPUS_ARM_NO_SILK_ASM
disables them.

Measured on the e200v1, silk_5.opus (WB SILK), with the previous commit:
36.31 -> 28.85 MHz, -20.5%.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ic1fd5777e91d182248f43954e4b6ae977309dc5d
2026-09-30 08:21:46 -04:00
Marcin Bukat
89e9ade855 rk27generic: FM radio screen keys, tuner noted as an RDA5807P
The FM screen had no actions for the rk27xx generic keypad; give it those
its keymap already maps (menu, play, stop, exit) in radio.c.

The board's tuner is an RDA5807P. It keeps being driven as a TEA5767, in
the chip's compatible mode, as the original firmware does: tuning, seek
and the stereo indicator work so, and the RDA mode would bring nothing
here - this variant has no RDS. Say so next to CONFIG_TUNER.

The tuner's audio is on the codec's line input 1: only that line is
powered and mixed in while the radio plays (RK27XX_CODEC_FM_LINE 1). With
line 2 instead the radio is silent.

Tested on the rk27generic board: manual tuning, seek, stereo indicator and
audio.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I2135ee484705ff0fce6d88e73288d8ed2aec6c2d
2026-09-30 08:07:47 -04:00
Marcin Bukat
19caf27567 rk27xx codec: mix in only the tuner's line, keep the DAC
audiohw_set_monitor() switched the output mixer from the DAC to both line
bypasses: voice and beeps went silent while the radio played, and a line
nobody listened to was mixed in, with its noise. Both line inputs were
also powered from start-up on.

- the target names the line its tuner is on, RK27XX_CODEC_FM_LINE (1 or
  2); both are used where it does not say
- monitoring adds that line's bypass to the DAC instead of replacing it
- the line inputs stay in standby until monitored, and go back after

Only rk27generic uses the internal codec - the other rk27xx targets
have external DACs or codecs.

Tested on rk27generic: the radio plays through the monitored line, key
clicks stay audible over it, and playback is unaffected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I177fdf605e4d997159898c868b2186c9584eb19a
2026-09-30 08:07:15 -04:00
Vencislav Atanasov
88f3d21890 manual: Fix case of "iPod"
The special iPod_Control folder's case is also fixed.

Change-Id: I9a65cf9034774ddb8c3b2de00ff1c27e35710d20
2026-09-30 07:58:19 -04:00
Michael Giacomelli
b6b2d95309 opus: fixed-phase SILK resampler interpolation
The 8, 12 and 16 kHz to 48 kHz steps visit only two or three FIR phases
in a fixed cycle, so each set of input samples is read once and reused
across outputs.  Bit-exact; OPUS_NO_SILK_FIXED_PHASE disables it.

Measured with silk_5.opus (WB SILK):
e200v1: 36.31 -> 33.38 MHz, -8.1%
Clip+:  21.66 -> 20.93 MHz, -3.4%

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Icb0f8ded62739dfee1f574e4888a54c778aa3d53
2026-09-30 07:54:43 -04:00
Solomon Peachy
67ba9c3121 imx233: re-enable utf8proc and associated functionality.
Will require updated bootloaders!

Change-Id: Id9a3da0b05fe27f7a3d27443a2f15742455d86c2
2026-09-29 22:39:49 -04:00
Vencislav Atanasov
f012c09eed Bulgarian translation update
Change-Id: Id13ca6875a08eb2e1843dc6ecaa15fd0f09b96c4
2026-09-29 20:38:15 -04:00
Solomon Peachy
9ab4bdcf91 Translation updates:
Polish (Adam Rak)
Simplified Chinese (Wang Ji)
Slovak (Matej Golian)
Turkish (Mustafa Yıldız)
US English (Myself)

Change-Id: Icab7a33af666636ca7c4e7aadd517fbc82b062b2
2026-09-29 18:33:47 -04:00
Solomon Peachy
bbe37187d8 imx233: Increase bootloader's firmware buffer size to 2MB
Bootloaders with this change are now able to boot rockbox binaries over
1MB.  (1.5MB buffer led to bootloader hanging)

Change-Id: I540bd4146aaa7236df93e74f6f2c69aa32e4a874
2026-09-29 15:15:45 -04:00
Solomon Peachy
34368013c1 h1x0/h3x0: Get rid of redundant cut-down bidi_l2v() function
The one in the main bidi.c is already cut-down for bootloader builds

Change-Id: I4465419393b0eda91fb69bd4c3353f7c31e1e98d
2026-09-29 10:16:26 -04:00
Solomon Peachy
0b2caf7338 configure: Clean up 'appextra' definitions.
The contents of appextra are added to the INCLUDES list, eg:

   appextra="recorder:hosted"

will result in this at compile time:

   INCLUDES += -I$(APPDIR)/recorder -I$(APPDIR)/hosted

With that in mind,

 * 'gui' and 'recorder' have been set for all targets other than
   the original charcell Archos. Globally set these instead of
   using them everywhere.
 * 'hosted' was effectively a no-op and removed entirely.
 * 'radio' was specified on a lot of targets that didn't have a radio,
   just make it global as well.

The net result is that only the android targets now define 'appextra' in
their configure entry.  A future patch will remove the need to specify
the ones that are now global.

Change-Id: I751284cde4785077c54405a8a10be819021e4255
2026-09-29 09:12:59 -04:00
Solomon Peachy
e1a18fa15c builds: Relegate Samsung YP-CP3 to "unusable" status for now
It's not part of the build farm, doesn't have a manual, and isn't
even listed on the www site or wiki yet.

Change-Id: I5fc79d0316717898f16ff794cba114a46472ae8f
2026-09-29 08:29:13 -04:00
Marcin Bukat
3689292b28 YP-CP3: recording from the microphone and FM radio
- config: HAVE_RECORDING, sources microphone and FM, 8-48 kHz
- wm8751.c: the YP-CP3's own audiohw_set_recsrc(). The rk27xx cannot
  send received samples straight back out, so what is heard of an input
  goes through the codec's analog bypass - the input PGA into the output
  mixers: the radio always, the microphone never. As in the original
  firmware, the radio passes the PGA at +12 dB when only listened to,
  and the microphone - mono, on RINPUT2 - gets +13 dB boost and is
  recorded by the right ADC onto both channels (the original firmware's
  noise gate is left out). The HD300's version assumes the microphone on
  INPUT3 and headphones on OUT1, and switches OUT2 - the YP-CP3's
  headphones - off.
- wm8751.c: the playback-only FM monitor added for the YP-CP3 goes; the
  radio is routed by audiohw_set_recsrc() now, as on the HD300
- wm8751.h: DATSEL, which ADC feeds each channel of the output data

Only partly tested on hardware: FM radio still plays, and the recording
screen's peak meter follows the microphone. Not yet tested: a recorded
file played back, recording FM, recording gain range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I3c25f4333f765d98dddc2fd722c111f8493bbe77
2026-09-29 09:52:13 +02:00
Marcin Bukat
3fbf975ecc YP-R0 keypad: recording screen and FM recording keys
The keymap had no recording screen context, so on the recording screen
no key produced ACTION_REC_PAUSE and recording could not be started; nor
did the FM screen have a record action.

- recording screen: User starts and pauses, held opens a new file;
  left/right set the gain of the selected line; Menu opens the settings
- FM screen: User records the radio (FM_RECORD enabled for this keypad)

User is the Rec key on the Samsung YP-CP3, which shares this keypad.

Tested only in a YP-CP3 build, not yet on hardware; the YP-R0 itself was
not built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I655865d0dcf3e72da4e2d1cba24bc296919ec261
2026-09-29 09:51:25 +02:00
Marcin Bukat
a33b0c7360 rk27xx: recording over I2S and HDMA channel 1
pcm-rk27xx.c had no recording at all. Add it for targets with
HAVE_RECORDING: HDMA channel 1 moves the I2S Rx FIFO into the recording
buffer - hdreq 7, fixed source, incrementing destination, 32-bit inc8
slices, the mirror of the playback channel and the setup the Samsung
YP-CP3's original firmware uses. Playback keeps channel 0, so the two can
run together.

- HDMA_ISR holds both channels' masks and flags; playback used to write
  all of it, clearing whatever the other channel had. Each channel now
  updates only its own bits, and INT_HDMA serves each channel's count
  down flag. Both channels start masked and clear.
- Recording cannot mask the shared interrupt, so pcm_rec_lock() defers a
  completed buffer to pcm_rec_unlock() instead.
- In master mode the I2S Rx side runs only while recording: started with
  nothing reading its FIFO it upsets playback. I2S_RXCTL gets the Tx
  frame format, plus bit 24 as the YP-CP3's original firmware sets it.
- audio-rk27xx.c routes inputs through audiohw_set_recsrc() on targets
  that record.

Only partly tested, on a YP-CP3: playback and FM radio still work after
the interrupt changes, and the recording screen's peak meter follows the
microphone, so samples arrive through the DMA. Not yet tested: playing
back a recorded file, recording FM, long recordings, recording while
playing. A known risk: a flag set by the hardware in the few cycles of
the read-modify-write of HDMA_ISR would be lost and stall that channel.
Other rk27xx targets build; their playback was not retested on hardware.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Idc64bce8075d0fc628c29767fc33beda4fff4342
2026-09-29 09:50:20 +02:00
Marcin Bukat
c922ef98c3 YP-CP3: Si4703 FM radio
The YP-CP3's tuner is a Silicon Labs Si470x at I2C address 0x20, an
Si4703 by the RDS the original firmware enables. The firmware drives it
the Si470x way - writes from register 2, reads from 0x0A - starts its
oscillator with TEST1 = 0x8100 and a 500 ms wait before ENABLE, and has
no power or reset line for it.

- config: CONFIG_TUNER SI4700 with RDS, polled (no interrupt line
  needed), and FM radio as an input source
- si4700.c: the YP-CP3 starts the oscillator as the Sansas do
- power-ypcp3.c: tuner power stubs - there is nothing to switch
- the rk27xx tuner I2C glue, and "radio" in the target's configure entry
- wm8751.c: audiohw_set_monitor() for a WM8750 target that plays the
  radio but cannot record (rk27xx has no recording yet). The tuner, on
  LINPUT1/RINPUT1, goes through the input PGA at +12 dB - as in the
  original firmware - into the output mixers, the DAC staying in the mix.
  The existing monitor routing lives in the recording code and switches
  OUT2 off, which is the YP-CP3's headphone output.

Tested on a YP-CP3: stations tune and play at a sane level.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ic097fc85dbd7fb71fcc28c97a9d378fa09599e79
2026-09-29 09:47:51 +02:00
Marcin Bukat
a35f344eef YP-CP3: WM8750 audio
The YP-CP3 uses Wolfson WM8750. Headphones are wired on OUT2 and
a headphone amplifier enabled by GPIO F2, active high -
all RE from the original firmware.

The original firmware runs the codec as I2S master in its 12 MHz "USB
mode", fed a fixed 12 MHz MCLK, which puts 44.1 kHz at 44.118. Rockbox
instead makes the rk27xx the master and clocks the codec from the codec
PLL at exactly 256 fs (CODEC_SLAVE, as every other rk27xx target with an
external codec), so the codec's CLOCKING register is its normal-mode
256 fs setting at every rate. 96 kHz is left out: the WM8750 cannot take
it at 256 fs.

- config: HAVE_WM8750, CODEC_SLAVE, rates 8-48 kHz; the WM8750 has
  hardware tone controls, so HAVE_SW_TONE_CONTROLS goes
- ypcp3/wmcodec-ypcp3.c: register writes over the rk27xx I2C driver
- wm8751.c: on the YP-CP3, power on and drive OUT2 instead of OUT1, set
  the volume there, and switch the amplifier with the outputs
- english.lang: the YP-CP3 gets the bass/treble cutoff settings the
  WM8750 brings

Tested on a YP-CP3: playback at 44.1 and 48 kHz on headphones, pitch and
volume correct.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I870038fb6a21a9c26b025e3df7c220fd925f49f6
2026-09-29 09:34:02 +02:00
Marcin Bukat
f7655e226c Samsung YP-CP3: Seiko S-35390A on I2C as RTC
Found in the original firmware by its command-in-address protocol
and bit-reversed data; the original firmware leaves it
in 12-hour mode, which the driver now handles.

Change-Id: I9f4147d3057aaa6aa498a1750cb4e746d69b1be6
2026-09-29 09:30:23 +02:00
Marcin Bukat
2190a31dac Samsung YP-CP3 define power hold pin
Change-Id: I9fbfa00b37d3f2194df36f808fa01e2a2eab0e59
2026-09-29 09:29:38 +02:00
Marcin Bukat
0dc08e53a9 S-35390A RTC: bring the driver back, handle 12-hour mode
The S-35390A keeps the hour either as 0-23 or - its default after a
power-on reset - as 0-11 plus a p.m. flag, selected by the 12/24 bit of
status register 1. The driver assumed 24-hour mode and never set it: it
masked the p.m. flag off, so on a chip left in 12-hour mode every
afternoon read as morning, and writing an afternoon time stored an
out-of-range hour.

Read the mode in rtc_init() and convert the hour both ways. The chip's
mode is left alone, as another firmware on the same player may depend on
it - the Samsung YP-CP3's original firmware runs it in 12-hour mode and
never touches the bit. If the status register cannot be read, the driver
keeps assuming 24-hour mode, as before.

Upstream removed the driver with its only users, the Meizu M3/M6 and
Samsung YP-S3 ports (1a33d7990a); the Samsung YP-CP3 needs it, so it
comes back here, with RTC_S35390A and its SOURCES entry.

Also pick the I2C header by CONFIG_I2C, so rk27xx targets can use the
driver; i2c_read()/i2c_write() have the same shape there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I54d8c8cfaa1b88237f6c4b08d2a510ec9fce8ec5
2026-09-29 09:20:12 +02:00
Marcin Bukat
8a53c15d1c rk27xx: only list PLL settings for the rates a target has
set_codec_freq()'s table of codec PLL settings names every rate from 8 to
96 kHz by its HW_FREQ_ index, which exists only for rates in the target's
HW_SAMPR_CAPS. Every CODEC_SLAVE target so far has all of them; a codec
without 96 kHz at 256 fs - the WM8750 - leaves HW_FREQ_96 undefined and
the table no longer builds.

Wrap each entry in HW_HAVE_xx_(), as the codec drivers' tables do. For
the existing targets the table is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ifab688ffa6f83c5319d686fcf40fc2b887c75d24
2026-09-29 09:06:36 +02:00
Marcin Bukat
98f162b212 New target: Samsung YP-CP3 (rk27xx)
Scaffolding for a port, starting from the rk27xx generic target: configure
entry 146 (target id 117, model number 132), config/samsungypcp3.h, and
firmware/target/arm/rk27xx/ypcp3/.

- LCD: the rk27xx LCD interface (lcdif-rk27xx.c) with this panel's init
  sequence, from RE. See g#1050. Looks like SPFD5420A 18-bit bus,
  400x240 landscape. It differs from the generic panel's sequence in the
  gamma curve and in not writing VCOM_HV1.

- Backlight: PD4 / PWM0 with the generic board's timing, which the hwstub
  work found to be the same.

- Storage: the microSD slot. Card detect is PC7, active low,
  as on the generic board.

- Keys: the YP-R0's key set - five-way yog, Back, Menu, Rec/User, Power -
  so the target uses SAMSUNG_YPR0_PAD and its keymaps. Eight keys sit on
  two resistor ladders on the LSADC, found in the original firmware and
  measured on a unit:
      channel 1   up 158, down 295, select 435, left 561, right 687
      channel 2   menu 155, back 292, user 431
  each key owning half a step either side of its reading;
  power is GPIO C1, active high.

Builds as firmware and as bootloader. Status 3 (unusable) in builds.pm.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Iff4984023415f341ca7507af6b5b2b551201e953
2026-09-29 08:53:27 +02:00
Michael Giacomelli
2bb498b963 jpeg: fix decoding of grayscale images with 2x2 sampling
A single-component (grayscale) scan is non-interleaved, so its MCU is
one 8x8 block regardless of the sampling factors in the frame header
(T.81 A.2.2). Some encoders write H=2,V=2 for the lone component, which
sent both the imageviewer plugin decoder and the core loader down the
4:2:0 path: 6 blocks per 16x16 MCU, the image treated as colour, and
the entropy data overrun.

Force 1x1 sampling for single-component frames when parsing SOF0 so
these images use the 4:4:4 layout with one block per MCU. Also add the
missing else in fix_headers() in the core loader, matching the plugin.

Tested on a Sansa e200 with both the plugin and the core loader, and
the plugin in the e200 simulator and built for PC and for ARM (qemu).

Fixes FS#13749.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Iac2f925aab8cd602930470dca5da7dfb44e15961
2026-09-28 22:38:41 -04:00
Michael Giacomelli
89c38484ea fix missing else in jpeg decoder.
This didn't actually break anything since the error case wasn't
handled anyway but not a good idea to leave alone.
2026-09-28 22:38:41 -04:00
Michael Giacomelli
04ecb3c645 flac: don't divide by zero when STREAMINFO has no sample count
A total sample count of 0 means unknown. It made the track length 0 and the
bitrate estimate in flac_init() divided by it, crashing the codec (FLAC
decoder testbench file 45). Report a bitrate of 0 in that case.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 16:35:14 -04:00
Michael Giacomelli
a81fd7b77f flac: handle zero-width escaped rice partitions
An escape code with a raw bit width of 0 means every residual in the
partition is zero. get_sbits(&gb, 0) shifts by 32, which is undefined and
returned stale cache bits instead of 0, so such streams decoded to garbage
(FLAC decoder testbench file 64).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 16:35:14 -04:00
Michael Giacomelli
8f38274e90 warble: zero the mp3entry before reading metadata
print_mp3entry() dereferences mb_track_id, but get_metadata() does not set
every field of the uninitialized stack struct. For FLAC files this left
garbage in the pointer and warble segfaulted in strlen about a third of the
time, before decoding started. Clear the struct first.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-28 16:35:14 -04:00
Solomon Peachy
e9a6b58870 toolchain: Fix hosted arm/mips toolchain build with texinfo 7.0/7.1
A crash bug in those versions of texinfo (fixed in 7.20) caused the
glibc manual to fail to build.  There is no build-time argument to
disable the manual, but there is a version check that gracefully
accomplishes the same thing.

So, add 7.0/7.1 in the glibc configure script blacklist.

Change-Id: If841aceeb7986db8274d145a5ea317278890eb30
2026-09-28 15:17:14 -04:00
Michael Giacomelli
c47b2e1be2 opus: name the ARM inline-asm gates after the cores they cover
Upstream's OPUS_ARM_INLINE_ASM means any ARM with inline assembly, with
OPUS_ARM_INLINE_EDSP layered on top for ARMv5E.  config.h instead defines
exactly one of them per core, so the names read as broader than they are,
and code added ARM_ARCH tests beside them to pin the scope down.  Renamed
to OPUS_ARM_ASM_ARMV4_ONLY and OPUS_ARM_ASM_ARMV5E_AND_LATER throughout
celt and silk, upstream files included; README.rockbox records it for the
next libopus sync.

No code change: opus.elf disassembly and section sizes are identical
before and after on ARMv4 (e200v1), ARMv5E (Clip+) and ARMv6 (iPod Nano
4G).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I89932d348dedd76748a1bc7b3f2e7de1c5be49c8
2026-09-28 12:10:57 -04:00
Marcin Bukat
d3893ead3a rk27xx: keep interrupt and bulk endpoints in separate groups
USB mass storage writes ran at 0.03 MB/s in the firmware - to the NAND
and to the SD card alike - while the bootloader, with the same driver,
wrote the same NAND at 2 MB/s. The firmware adds a HID interface, and
without it writes ran at full speed.

The UDC's endpoints come in groups of three - bulk OUT, bulk IN,
interrupt IN: 1-3, 4-6 and so on - and allocation handed out the first
free endpoint of each type, so HID's interrupt endpoint 3 landed in the
group of mass storage's bulk endpoints 1 and 2. The host polls it every
16 ms, the idle endpoint NAKs, and each poll costs the group's bulk
traffic: writes advanced about one packet per poll. Polled every 125 us
instead, they all but stopped; moved to endpoint 6, in a group of its
own, they ran at 2.36 MB/s, as without HID.

Never give an interrupt endpoint a group with bulk endpoints in use, or
the other way round, whichever class asks first. Since which endpoints
are available then depends on what is already allocated, the driver
tracks the allocation itself - option 2 of usb_drv.h, as usb-designware
does - with its context in usb-rk27xx.h, which usb_core.c includes before
usb_drv.h. HID keeps working.

Tested on a generic rk2705 with ums_stress.py over USB mass storage to
the SD card: 0.03 MB/s with HID on endpoint 3, 2.36 MB/s with it on
endpoint 6 - the allocation this change produces for mass storage plus
HID. (Measured with the driver's earlier allocator, before the USB core
took allocation over; this carries the same rule into the new scheme.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Ib80ed206a3705f2c76fc8457b5c0a54d60a46402
2026-09-28 16:55:21 +02:00
Marcin Bukat
4dcb5bae9d rk27xx: fix busy-wait asm that modifies an input-only operand
delay_nop() in lcd-rk27generic.c and udelay() in system-rk27xx.c both
count a register down with subs, but pass it as an input operand only:

    asm volatile ("1: subs %[n], %[n], #1\n bne 1b" : : [n] "r" (cycles));

That tells GCC the register is unchanged afterwards, so it is free to
load a constant once and reuse the register for every later call with the
same argument. Current GCC does exactly that in lcd_display_init():

    ldr   r4, =10000        @ first delay_nop(10000)
    subs  r4, r4, #1        @ ... counts r4 down to 0
    bl    lcd_write_reg
    subs  r4, r4, #1        @ next delay_nop(10000): r4 not reloaded,
                            @ 0 - 1 wraps, loop runs 2^32 times

At 4 cycles per iteration and 200 MHz that is 85.9 s per wrapped call.
Nine calls wrap, so lcd_init() took 9 x 85.9 = 773 s. Measured on a
generic rk2705 with a tick timestamp either side of lcd_display_init():
77320 ticks at HZ=100, i.e. 773.2 s. With this fix it is 9 ticks, clear
loop included.

That is why lcd_init() looked like a hang on current toolchains while it
worked when the port was written. It also explains why no LCDC clock,
divider, gating or strobe-timing change had any effect: the time was
never spent in the LCD controller.

udelay() happens to work today because its count is computed at run time
on each call, but it has the same undefined behaviour and gets the same
fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: Iecdd6cca0701c35bce3427f359a9a638b21291b5
2026-09-28 16:22:13 +02:00
Solomon Peachy
3c09d4570f FS#14012 - Latvian Translation Update (Renalds Belaks)
Change-Id: I904a8e5b688ff9b36220bf6631fa5369e4b3d025
2026-09-28 09:08:28 -04:00
Marcin Bukat
9bcdd30293 usb_storage: flush storage when the host stops or ejects the unit
A host that is done with a mass-storage device - "safely remove", eject,
udisksctl power-off - sends START STOP UNIT with the start bit clear, and
may cut power right after. usb_storage only marked the LUN ejected.

Storage drivers can still hold data in RAM at that point: a flash
translation layer keeps part-written pages until a later write completes
them, and HAVE_STORAGE_FLUSH exists so they can be committed - but only
shutdown and ROLO called it. On a device unplugged after a proper eject
and then losing power, that data was lost although the host had done
everything right.

Call storage_flush() on stop and on eject, on targets that define
HAVE_STORAGE_FLUSH. The SCSI handler runs in the USB thread, as do the
reads and writes, so the flush cannot race them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I5b5811858c75dfb3ee89535ab59f4a19663945df
2026-09-28 08:39:24 +02:00
Solomon Peachy
2745e0b973 FS#14011: Handle usb hosts whose first request is SET_ADDRESS (Anthony Fletcher)
Thanks for the SET_ADDRESS rework. I think it leaves one case uncovered:
a host whose first request is SET_ADDRESS ends up with a device whose
interfaces are all numbered 0.

Two things still depend on the core seeing a request before the address arrives:

  1. usb_core assigns interfaces and endpoints only on the first control
     request it handles in DEFAULT. When SET_ADDRESS comes first, the driver
     completes it and usb_core_set_address() moves the state to ADDRESS. So
     allocate_interfaces_and_endpoints() never runs.
  2. Under USB_DETECT_BY_REQUEST, usb.c enables the class drivers only
     on a USB_TRANSFER_COMPLETION event. The SET_ADDRESS status stage now
     completes inside the driver, so the drivers are still disabled when the
     address arrives.

Change-Id: Ifacb8b07cbdefb0dee3d414c2257a50a08759f3d
2026-09-27 19:36:21 -04:00
Solomon Peachy
583f27d5e5 FS#14002 - German Language Patch (Wilfried Winkler)
Change-Id: I83d42092b192eb93df680bd98c724d81f65ddca1
2026-09-27 19:36:21 -04:00
neofright
f5076456fe Fix path bug in bootloader/hibyos_linux.c
run_file() joins /mnt/sd_0 and the filename without a /, so /bin/sh cannot open any script and always returns 2.

The path bug has been fixed and the buffer size adjusted and freed after execution.

GPT 6 Sol did the work. I'm just the meat proxy.

Change-Id: I644a773b2bd707e0ee2d8c70c91b7a6075cf2622
2026-09-27 22:03:30 +01:00
Solomon Peachy
e2efcb906a manual: Correct download links for daily/dev builds.
Change-Id: Iba3822386d2ed7c2f91d635f63014d63b652decc
2026-09-27 11:06:40 -04:00
Solomon Peachy
636ae404f7 misc: forums.rockbox.org -> www.rockbox.org/forums
Change-Id: Ieddb1d534aa15e3e931eb66e9380276602cfd0c5
2026-09-27 10:46:01 -04:00
Paul Sauro
9aa2d7fe94 usb: accept replacement SETUP after an abandoned control transfer
A host can replace an unfinished control transfer with a new SETUP. ARC
and DesignWare flush EP0 without reporting completion callbacks, leaving
the core waiting for a data/status packet that will never arrive.

Explicitly notify the core after both directions and stale completion
bits have been cancelled. Return an abandoned data/status stage to READY.
If a queued or running handler still owns the request and data buffer,
keep that ownership and suppress its response; dispatch only the latest
replacement when it returns. A driver-owned SET_ADDRESS can also cancel
a deferred request without passing its SETUP to the core.

Do not overwrite an arbitrary busy state in usb_core_setup_received().
ARC cancellation is a prerequisite in the preceding patch; DesignWare
cancels both EP0 directions before notifying and rearming reception.

Change-Id: Ia8e0a68fe47ccab952168da24a2f76e311ca2b15
2026-09-27 09:19:39 -04:00
Michael Giacomelli
b12ef5e6f8 opus: gate the ARMv5E kernels for ARMv6 too
Four `ARM_ARCH == 5` checks -- in SOURCES and celt/arm/{bands_arm,
comb_filter_arm,vq_arm}.h -- excluded ARMv6 from every ARMv5E kernel:
denorm_band, haar1, comb_filter_const, celt_sat, deemphasis_stereo_simple,
exp_rotation1 and normres_scale all silently fell back to plain C on
ARM1136/ARM1176, since ARMv6 is a strict superset of the EDSP instructions
those kernels use. Widened to ARM_ARCH >= 5, matching config.h's own
OPUS_ARM_INLINE_EDSP gate, which was already ARM_ARCH > 4.

These four can't be fixed at the commits that introduced them: those
commits are already merged into master under different SHAs. A fifth
instance of the same bug, in celt/arm/mdct_armv5e.h, was fixed at its
origin commit instead, since that one is still open for review.

Verified on both native ARMv6 targets (iPod Nano 4G, ARM1176JZ-S; Gigabeat
S, ARM1136JF-S) and the hosted Samsung YP-R0 (ARM1176JZ-S, cross toolchain
built for the occasion): all three now link and call all 16 ARMv5E
kernels, where they linked and called zero before this fix. Decoded PCM
bit-identical to the ARMv5E build under qemu.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Change-Id: I7e6f6b421b9c0203812fb45d2258c7eb81738d98
2026-09-27 05:52:23 -04:00
Michael Giacomelli
5a6935047e opus: hold cwrsi's row pair, and test it with one comparison
53% of the dimensions a decode walks hold no pulses, and that arm leaves
_k alone, so the two CELT_PVQ_U_ROW pointers stay valid.  U is
non-decreasing in _k, so p <= _i < q is the single unsigned test
(_i-p) < (q-p).  Bit-exact over 8.2M samples.

Modelled: -0.40% ARMv4, -0.78% ARMv5E; the function -4.8% and -7.1%.
Measured: e200v1 39.19 -> 38.96 MHz, Clip+ 28.13 -> 28.08 MHz.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: Id50be222e101aeabd9a1f4cf5380d3244da610ff
2026-09-27 05:37:13 -04:00
Michael Giacomelli
93d564426b opus: ARMv4 exp_rotation1
At stride 1 the rotation chain writes X[i+stride] and reads it straight
back, so one load an iteration is redundant and one store is dead.  The
kernel carries that value, narrowed, since mul reads all 32 bits where
smulbb does not.  Bit-exact over 8.2M samples.

Modelled: -0.87% ARMv4, the function -10.0%.
Measured: e200v1 39.59 -> 39.19 MHz.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: Idbd1a088bc805fecfb9ee54fc372ad16a7d91606
2026-09-27 05:35:00 -04:00
Michael Giacomelli
a51adaac4f opus: place the hot decode path in IRAM on PP5022/5024
34 functions and the ARMv4 kernels, chosen by a greedy fill of the free
codec IRAM window ranked by cycles per byte.  The mixed-radix
butterflies give their IRAM back, being unreachable under the prime
factor transform.

The cycle model does not see this at all: it models no instruction cache.
Measured: e200v1 48.96 -> 42.60 MHz; reclaiming the mixed-radix IRAM was
a further -0.52%.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I9e22025cba99521750a3b664cd0d59357fcd0810
2026-09-26 17:48:52 -04:00
Solomon Peachy
40fdf6ac11 libopus: Fix yellow and red in da9df96c30
* simulator warnings
 * non-arm warnings
 * armv7-m errors
 * armv7-a errors

Change-Id: I285ab466c07170e632f1bec488eb471bcbd4a566
2026-09-26 14:49:52 -04:00
Michael Giacomelli
da9df96c30 opus: Good-Thomas FFT for the backward MDCT
Every 48 kHz CELT length is 15 times a power of two and the factors are
co-prime, so the inter-stage twiddles -- 73% of the FFT multiplies at
N=480 -- vanish.  New pfa_fft15 and mdct_postrot_pfa kernels on both
cores; accuracy also improves 0.3 to 0.4 dB against opusdec.

Modelled: -6.17% ARMv4, -1.82% ARMv5E.
Measured: e200v1 42.33 -> 40.10 MHz, Clip+ 29.30 -> 28.24 MHz.
Rescheduling these kernels, folded in here, measured a further -0.75% on
e200v1 and -0.39% on Clip+.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: Ifa4a30d1045e905522828958949954615faa440d
2026-09-26 13:57:35 -04:00
Michael Giacomelli
7b4d1a7f75 opus: dual_inner_prod on ARMv5E
One ldr fetches two celt_norm coefficients and smlabb/smlatt take the
halves apart; scalar fallback when the three pointers disagree on
alignment.

Modelled: -0.88% ARMv5E.
Measured: Clip+ 28.13 -> 28.08 MHz, the same build with and without it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I79719132ccecfb7664616bca019e3856ee3479da
2026-09-26 13:26:45 -04:00
Paul Sauro
841007dfa1 usb: let controller drivers handle SET_ADDRESS requests
Handle SET_ADDRESS directly when each controller receives SETUP, before
passing other requests to the core. Cancel transfers, send the status
response in the driver and queue usb_core_notify_set_address(); the core
only updates its address/configuration state. Remove usb_drv_set_address
and avoid a request callback from the core back into the controller.

Keep status completions for this driver-owned request out of the core EP0
state machine. ARC writes DEVICEADDR and notifies after successful status
IN completion; other controllers retain their existing register/status
ordering or automatic address handling. Use IRQ-local operations on
DesignWare rather than helpers which unconditionally re-enable its IRQ.

Take the low seven bits of wValue; do not impose new validation on the
unspecified wIndex/wLength fields. Convert all eleven firmware backends;
the separate hwstub API is unchanged.

Change-Id: I7b96275df90c14ef4a9954f04ac6fdc004ec8d6c
2026-09-26 13:23:01 -04:00
Solomon Peachy
bd615cf125 FS#13996: Have audio_hard_stop() kill the PCM output path entirely
We already shut down the playback path and the voice path, but that
doesn't necessarily mean the PCM hardware is idle.

Add a call to pcm_play_stop() to ensure the PCM sink is completely idle.
This will prevent a badly-timed callback from firing during a ROLO
operation.

Change-Id: I1eb8c105895fb47bc3d0af91b4d87345f5399aa4
2026-09-25 16:03:03 -04:00
Paul Sauro
3bd18f5a44 usb iap: correct sample rate descriptors and packet cadence
Advertise only the implemented 32, 44.1 and 48 kHz stereo formats. Add
128-byte packets at 32 kHz and wrap the 44.1 kHz cadence at ten packets;
a uint8_t wrap at 256 otherwise emits extra samples every cycle.

Use the serialized UAC header length (including baInterfaceNr), maintain
the active alternate setting, accept alt 0 on non-streaming interfaces,
and retain the last valid sample rate when a SET_CUR request is rejected.

Change-Id: I41dab55fc0c7d2e6474492f97062e9838bc3aebf
2026-09-25 13:49:30 -04:00