OAKLAND, Calif. (AP) -- Danny Duffy can blow away hitters with a mid-90s fastball.
He's learning that his softer stuff can be just as effective.
Duffy pitched seven innings of three-hit ball, and the Kansas City Royals snapped a six-game skid with a 2-0 victory over the Oakland Athletics on Saturday.
Duffy (3-6) struck out a season-high 10 and walked three.
Royals catcher Salvador Perez noticed early his team's ace had a devastating changeup, and he wasn't shy about calling it -- even in fastball counts.
"Salvy called a fantastic game and certain times revealed themselves where we went back-to-back-to-back-to-back changeups," Duffy said.
"You don't do that very often when you throw in the mid-90s, but it was enough to keep people off balance today."
Chris Bassitt (0-1) also allowed three hits in seven innings in his first appearance since undergoing Tommy John surgery on May 6, 2016. He struck out six and walked one, allowing one run -- on Paulo Orlando's RBI single in the second inning.
Orlando's hit snapped a 0-for-14 stretch.
The Royals scored again in the ninth on Alex Gordon's home run -- his fifth -- off Yusmeiro Petit.
Kevin McCarthy pitched the eighth and Kelvin Herrera worked a scoreless ninth to complete the four-hitter and earn his 14th save in 15 opportunities.
With the Royals' offense sputtering, manager Ned Yost shuffled the lineup, moving Gordon into the cleanup spot, Mike Moustakas from third to second and Perez from cleanup to third in the batting order. Gordon's homer was the only hit by the trio.
Moustakas played his 900th career game for the team -- becoming the 13th player in Royals history to reach that plateau -- and started at first base for the first time.
Bassitt was called up from Triple-A Nashville for a spot start in place of Trevor Cahill, who is out with an Achilles injury. He didn't arrive in Oakland until late Friday night.
Bassitt is the seventh starter the A's have sent to the mound in as many days and the 11th different starter they've used this season.
He lost his seventh straight decision dating to April 28, 2016. His last win was on Aug. 4, 2015, against Baltimore.
The 29-year-old acknowledged he's had doubts about his baseball future.
"There was some dark days," Bassitt said. "Even this year there was some dark days."
The Royals beat Oakland for the second time in six tries this season.
The A's are 8-14 against left-handed pitchers this season. They're 25-18 vs. righties.
Yost challenged two calls on the same play in the top of the fourth. With Alcides Escobar at second with two outs, Orlando hit a grounder to A's shortstop Marcus Semien, who threw wide to first. Escobar tried to score from second on the play. First base umpire Bill Welke ruled that first baseman Matt Olson had applied a swipe tag on Orlando, and home plate umpire Tony Randazzo ruled that catcher Josh Phegley tagged out Escobar. The play at first was overturned and the play at home was upheld after a replay review that lasted 3 minutes, 37 seconds.
Royals: RF Jorge Soler was out of the lineup with a bruised left toe, Yost said. Soler left Friday's game after fouling a ball off his foot. X-rays taken Friday night were negative.
Athletics: LHP Ryan Buchter (strained left shoulder) is with Single-A Stockton. He threw 20 pitches to hitters on Friday night and reported no discomfort, manager Bob Melvin said. ... Nick Martini was optioned to Triple-A Nashville to make room on the roster for Bassitt. ... OF Boog Powell (right knee strain) has worked out at the A's extended spring training facility in Arizona and is expected to start a rehab assignment soon, Melvin said.
A's LHP Sean Manaea (5-6, 3.59 ERA) is 1-4 with a 6.63 ERA in his last seven starts. He hopes to get back on track in Sunday's series finale. RHP Brad Keller (1-2, 2.12 ERA) will make his third start since moving into the rotation.